aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-05-25 18:43:54 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2017-06-10 13:08:21 +0200
commit6adfcf74664a30021f12cc84e00a7cd471ee81a1 (patch)
tree5f9398057fe84a68ccd1d72f6d83a2aaa020bea4
parentbb64c6b3ba80f8ef844bae59e270ca9e3b43d1fd (diff)
Status display
Alows to show status of current channels and users
-rw-r--r--src/amps/amps.c17
-rw-r--r--src/amps/amps.h1
-rw-r--r--src/amps/transaction.c36
-rw-r--r--src/amps/transaction.h1
-rw-r--r--src/anetz/anetz.c24
-rw-r--r--src/bnetz/bnetz.c27
-rw-r--r--src/cnetz/cnetz.c17
-rw-r--r--src/cnetz/cnetz.h1
-rw-r--r--src/cnetz/transaction.c38
-rw-r--r--src/cnetz/transaction.h1
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/debug.c2
-rw-r--r--src/common/display.h10
-rw-r--r--src/common/display_status.c147
-rw-r--r--src/common/main_common.c19
-rw-r--r--src/nmt/nmt.c24
16 files changed, 354 insertions, 12 deletions
diff --git a/src/amps/amps.c b/src/amps/amps.c
index d180a4f..5d57d63 100644
--- a/src/amps/amps.c
+++ b/src/amps/amps.c
@@ -272,12 +272,29 @@ const char *amps_state_name(enum amps_state state)
return invalid;
}
+void amps_display_status(void)
+{
+ sender_t *sender;
+ amps_t *amps;
+ transaction_t *trans;
+
+ display_status_start();
+ for (sender = sender_head; sender; sender = sender->next) {
+ amps = (amps_t *) sender;
+ display_status_channel(amps->sender.kanal, chan_type_short_name(amps->chan_type), amps_state_name(amps->state));
+ for (trans = amps->trans_list; trans; trans = trans->next)
+ display_status_subscriber(amps_min2number(trans->min1, trans->min2), trans_short_state_name(trans->state));
+ }
+ display_status_end();
+}
+
static void amps_new_state(amps_t *amps, enum amps_state new_state)
{
if (amps->state == new_state)
return;
PDEBUG_CHAN(DAMPS, DEBUG_DEBUG, "State change: %s -> %s\n", amps_state_name(amps->state), amps_state_name(new_state));
amps->state = new_state;
+ amps_display_status();
}
static struct amps_channels {
diff --git a/src/amps/amps.h b/src/amps/amps.h
index db5fa64..6243f74 100644
--- a/src/amps/amps.h
+++ b/src/amps/amps.h
@@ -174,4 +174,5 @@ 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();
diff --git a/src/amps/transaction.c b/src/amps/transaction.c
index ea47a67..eac29e4 100644
--- a/src/amps/transaction.c
+++ b/src/amps/transaction.c
@@ -68,6 +68,39 @@ static const char *trans_state_name(int state)
}
}
+const char *trans_short_state_name(int state)
+{
+ switch (state) {
+ case 0:
+ return "IDLE";
+ case TRANS_REGISTER_ACK:
+ case TRANS_REGISTER_ACK_SEND:
+ return "REGISTER";
+ case TRANS_CALL_MO_ASSIGN:
+ case TRANS_CALL_MO_ASSIGN_SEND:
+ case TRANS_CALL_MT_ASSIGN:
+ case TRANS_CALL_MT_ASSIGN_SEND:
+ return "ASSIGN";
+ case TRANS_CALL_MT_ALERT:
+ case TRANS_CALL_MT_ALERT_SEND:
+ return "ALERT";
+ case TRANS_CALL_REJECT:
+ case TRANS_CALL_REJECT_SEND:
+ return "REJECT";
+ case TRANS_CALL:
+ return "CALL";
+ case TRANS_CALL_RELEASE:
+ case TRANS_CALL_RELEASE_SEND:
+ return "RELEASE";
+ case TRANS_PAGE:
+ case TRANS_PAGE_SEND:
+ case TRANS_PAGE_REPLY:
+ return "PAGE";
+ default:
+ return "<invald transaction state>";
+ }
+}
+
/* create transaction */
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan)
{
@@ -139,6 +172,7 @@ void link_transaction(transaction_t *trans, amps_t *amps)
while (*transp)
transp = &((*transp)->next);
*transp = trans;
+ amps_display_status();
}
/* unlink transaction from list */
@@ -157,6 +191,7 @@ void unlink_transaction(transaction_t *trans)
}
*transp = trans->next;
trans->amps = NULL;
+ amps_display_status();
}
transaction_t *search_transaction_number(amps_t *amps, uint32_t min1, uint16_t min2)
@@ -199,6 +234,7 @@ void trans_new_state(transaction_t *trans, int state)
{
PDEBUG(DTRANS, DEBUG_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state));
trans->state = state;
+ amps_display_status();
}
void amps_flush_other_transactions(amps_t *amps, transaction_t *trans)
diff --git a/src/amps/transaction.h b/src/amps/transaction.h
index 79fd467..5327481 100644
--- a/src/amps/transaction.h
+++ b/src/amps/transaction.h
@@ -49,4 +49,5 @@ transaction_t *search_transaction_callref(amps_t *amps, int callref);
void trans_new_state(transaction_t *trans, int state);
void amps_flush_other_transactions(amps_t *amps, transaction_t *trans);
void transaction_timeout(struct timer *timer);
+const char *trans_short_state_name(int state);
diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c
index 1362172..67a285e 100644
--- a/src/anetz/anetz.c
+++ b/src/anetz/anetz.c
@@ -63,12 +63,28 @@ const char *anetz_state_name(enum anetz_state state)
return invalid;
}
+void anetz_display_status(void)
+{
+ sender_t *sender;
+ anetz_t *anetz;
+
+ display_status_start();
+ for (sender = sender_head; sender; sender = sender->next) {
+ anetz = (anetz_t *) sender;
+ display_status_channel(anetz->sender.kanal, NULL, anetz_state_name(anetz->state));
+ if (anetz->station_id[0])
+ display_status_subscriber(anetz->station_id, NULL);
+ }
+ display_status_end();
+}
+
static void anetz_new_state(anetz_t *anetz, enum anetz_state new_state)
{
if (anetz->state == new_state)
return;
PDEBUG_CHAN(DANETZ, DEBUG_DEBUG, "State change: %s -> %s\n", anetz_state_name(anetz->state), anetz_state_name(new_state));
anetz->state = new_state;
+ anetz_display_status();
}
/* Convert channel number to frequency number of base station.
@@ -235,10 +251,10 @@ static void anetz_go_idle(anetz_t *anetz)
timer_stop(&anetz->timer);
PDEBUG(DANETZ, DEBUG_INFO, "Entering IDLE state on channel %d, sending 2280 Hz tone.\n", anetz->sender.kanal);
+ anetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_FREI);
/* also reset detector, so if there is a new call it is answered */
anetz_set_dsp_mode(anetz, DSP_MODE_TONE, 1);
- anetz->station_id[0] = '\0';
}
/* Release connection towards mobile station by sending idle tone for a while. */
@@ -247,9 +263,9 @@ static void anetz_release(anetz_t *anetz)
timer_stop(&anetz->timer);
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Sending 2280 Hz release tone.\n");
+ anetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_AUSLOESEN);
anetz_set_dsp_mode(anetz, DSP_MODE_TONE, 0);
- anetz->station_id[0] = '\0';
timer_start(&anetz->timer, RELEASE_TO);
}
@@ -257,10 +273,10 @@ static void anetz_release(anetz_t *anetz)
static void anetz_page(anetz_t *anetz, const char *dial_string, double *freq)
{
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Entering paging state, sending 'Selektivruf' to '%s'.\n", dial_string);
+ strcpy(anetz->station_id, dial_string); /* set station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_ANRUF);
anetz_set_dsp_mode(anetz, DSP_MODE_PAGING, 0);
dsp_set_paging(anetz, freq);
- strcpy(anetz->station_id, dial_string);
timer_start(&anetz->timer, PAGING_TO);
}
@@ -296,6 +312,8 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
/* initiate call on calling tone */
if (tone == 1) {
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Received 1750 Hz calling signal from mobile station, removing idle signal.\n");
+ strcpy(anetz->station_id, "unknown"); /* set station ID before state change, so status is shown correctly */
+
anetz_new_state(anetz, ANETZ_GESPRAECH);
anetz_set_dsp_mode(anetz, DSP_MODE_SILENCE, 0);
break;
diff --git a/src/bnetz/bnetz.c b/src/bnetz/bnetz.c
index a741e32..2fdeb03 100644
--- a/src/bnetz/bnetz.c
+++ b/src/bnetz/bnetz.c
@@ -84,12 +84,29 @@ const char *bnetz_state_name(enum bnetz_state state)
return invalid;
}
+void bnetz_display_status(void)
+{
+ sender_t *sender;
+ bnetz_t *bnetz;
+
+ display_status_start();
+ for (sender = sender_head; sender; sender = sender->next) {
+ bnetz = (bnetz_t *) sender;
+ display_status_channel(bnetz->sender.kanal, NULL, bnetz_state_name(bnetz->state));
+ if (bnetz->station_id[0])
+ display_status_subscriber(bnetz->station_id, NULL);
+ }
+ display_status_end();
+}
+
+
static void bnetz_new_state(bnetz_t *bnetz, enum bnetz_state new_state)
{
if (bnetz->state == new_state)
return;
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "State change: %s -> %s\n", bnetz_state_name(bnetz->state), bnetz_state_name(new_state));
bnetz->state = new_state;
+ bnetz_display_status();
}
/* Convert channel number to frequency number of base station.
@@ -253,10 +270,10 @@ static void bnetz_go_idle(bnetz_t *bnetz)
timer_stop(&bnetz->timer);
PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %d, sending 'Gruppenfreisignal' %d.\n", bnetz->sender.kanal, bnetz->gfs);
+ bnetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
bnetz_new_state(bnetz, BNETZ_FREI);
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
switch_channel_19(bnetz, 0);
- bnetz->station_id[0] = '\0';
#ifdef GEN_DIALSEQUENCE
if (bnetz->sender.loopback) {
bnetz_set_dsp_mode(bnetz, DSP_MODE_0);
@@ -271,23 +288,23 @@ static void bnetz_release(bnetz_t *bnetz, int trenn_count)
timer_stop(&bnetz->timer);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Entering release state, sending 'Trennsignal' (%d times).\n", trenn_count);
+ bnetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
bnetz_new_state(bnetz, BNETZ_TRENNEN);
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
switch_channel_19(bnetz, 0);
bnetz->trenn_count = trenn_count;
- bnetz->station_id[0] = '\0';
}
/* Enter paging state and transmit station ID. */
static void bnetz_page(bnetz_t *bnetz, const char *dial_string, int try)
{
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Entering paging state (try %d), sending 'Selektivruf' to '%s'.\n", try, dial_string);
+ strcpy(bnetz->station_id, dial_string); /* set station ID before state change, so status is shown correctly */
+ bnetz->station_id_pos = 0;
bnetz_new_state(bnetz, BNETZ_SELEKTIVRUF_EIN);
bnetz_set_dsp_mode(bnetz, DSP_MODE_0);
bnetz->page_mode = PAGE_MODE_NUMBER;
bnetz->page_try = try;
- strcpy(bnetz->station_id, dial_string);
- bnetz->station_id_pos = 0;
timer_start(&bnetz->timer, SWITCH19_TIME);
switch_channel_19(bnetz, 1);
}
@@ -477,6 +494,8 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm, double level, d
return;
}
bnetz->station_id[bnetz->dial_pos++] = digit;
+ /* update status while receiving station ID */
+ bnetz_display_status();
if (bnetz->dial_pos == 5) {
PDEBUG(DBNETZ, DEBUG_INFO, "Received station id from mobile phone: %s\n", bnetz->station_id);
bnetz->dial_mode = DIAL_MODE_NUMBER;
diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c
index 0921723..5563841 100644
--- a/src/cnetz/cnetz.c
+++ b/src/cnetz/cnetz.c
@@ -182,12 +182,29 @@ const char *cnetz_state_name(enum cnetz_state state)
return invalid;
}
+void cnetz_display_status(void)
+{
+ sender_t *sender;
+ cnetz_t *cnetz;
+ transaction_t *trans;
+
+ display_status_start();
+ for (sender = sender_head; sender; sender = sender->next) {
+ cnetz = (cnetz_t *) sender;
+ display_status_channel(cnetz->sender.kanal, chan_type_short_name(cnetz->chan_type), cnetz_state_name(cnetz->state));
+ for (trans = cnetz->trans_list; trans; trans = trans->next)
+ display_status_subscriber(transaction2rufnummer(trans), trans_short_state_name(trans->state));
+ }
+ display_status_end();
+}
+
static void cnetz_new_state(cnetz_t *cnetz, enum cnetz_state new_state)
{
if (cnetz->state == new_state)
return;
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "State change: %s -> %s\n", cnetz_state_name(cnetz->state), cnetz_state_name(new_state));
cnetz->state = new_state;
+ cnetz_display_status();
}
/* Convert ISDN cause to 'Ausloesegrund' of C-Netz mobile station */
diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h
index 1856db4..4f0bebe 100644
--- a/src/cnetz/cnetz.h
+++ b/src/cnetz/cnetz.h
@@ -138,4 +138,5 @@ const struct telegramm *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz);
void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, struct telegramm *telegramm);
const struct telegramm *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz);
void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, struct telegramm *telegramm);
+void cnetz_display_status(void);
diff --git a/src/cnetz/transaction.c b/src/cnetz/transaction.c
index aed8998..b37a014 100644
--- a/src/cnetz/transaction.c
+++ b/src/cnetz/transaction.c
@@ -109,6 +109,7 @@ void link_transaction(transaction_t *trans, cnetz_t *cnetz)
while (*transp)
transp = &((*transp)->next);
*transp = trans;
+ cnetz_display_status();
}
/* unlink transaction from list */
@@ -127,6 +128,7 @@ void unlink_transaction(transaction_t *trans)
}
*transp = trans->next;
trans->cnetz = NULL;
+ cnetz_display_status();
}
transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask)
@@ -226,10 +228,46 @@ static const char *trans_state_name(int state)
}
}
+const char *trans_short_state_name(int state)
+{
+ switch (state) {
+ case 0:
+ return "IDLE";
+ case TRANS_EM:
+ case TRANS_UM:
+ return "REGISTER";
+ case TRANS_MA:
+ case TRANS_MFT:
+ return "PING";
+ case TRANS_VWG:
+ case TRANS_WAF:
+ case TRANS_WBP:
+ case TRANS_WBN:
+ return "DIALING";
+ case TRANS_VAG:
+ case TRANS_VAK:
+ case TRANS_BQ:
+ case TRANS_VHQ:
+ return "ASSIGN";
+ case TRANS_RTA:
+ return "ALERT";
+ case TRANS_DS:
+ return "DS";
+ case TRANS_AHQ:
+ return "AHQ";
+ case TRANS_AF:
+ case TRANS_AT:
+ return "RELEASE";
+ default:
+ return "<invald transaction state>";
+ }
+}
+
void trans_new_state(transaction_t *trans, int state)
{
PDEBUG(DTRANS, DEBUG_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state));
trans->state = state;
+ cnetz_display_status();
}
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans)
diff --git a/src/cnetz/transaction.h b/src/cnetz/transaction.h
index dea1e7f..3c78153 100644
--- a/src/cnetz/transaction.h
+++ b/src/cnetz/transaction.h
@@ -54,4 +54,5 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref);
void trans_new_state(transaction_t *trans, int state);
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans);
void transaction_timeout(struct timer *timer);
+const char *trans_short_state_name(int state);
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index fa26d21..0b74906 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -27,6 +27,7 @@ libcommon_a_SOURCES = \
../common/fm_modulation.c \
../common/sender.c \
../common/display_wave.c \
+ ../common/display_status.c \
../common/main_common.c
if HAVE_SDR
diff --git a/src/common/debug.c b/src/common/debug.c
index af056d2..bea7bb0 100644
--- a/src/common/debug.c
+++ b/src/common/debug.c
@@ -97,12 +97,14 @@ void _printdebug(const char *file, const char __attribute__((unused)) *function,
clear_console_text();
// printf("%s%s:%d %s() %s: %s\033[0;39m", debug_cat[cat].color, file, line, function, debug_level[level], buffer);
display_wave_limit_scroll(1);
+ display_status_limit_scroll(1);
#ifdef HAVE_SDR
display_iq_limit_scroll(1);
display_spectrum_limit_scroll(1);
#endif
printf("%s%s:%d %s: %s\033[0;39m", debug_cat[cat].color, file, line, debug_level[level], buffer);
display_wave_limit_scroll(0);
+ display_status_limit_scroll(0);
#ifdef HAVE_SDR
display_iq_limit_scroll(0);
display_spectrum_limit_scroll(0);
diff --git a/src/common/display.h b/src/common/display.h
index 9f476de..6f75662 100644
--- a/src/common/display.h
+++ b/src/common/display.h
@@ -28,6 +28,8 @@ typedef struct display_spectrum {
double buffer_Q[MAX_DISPLAY_SPECTRUM];
} dispspectrum_t;
+#define MAX_HEIGHT_STATUS 32
+
void get_win_size(int *w, int *h);
void display_wave_init(sender_t *sender, int samplerate);
@@ -35,6 +37,13 @@ void display_wave_on(int on);
void display_wave_limit_scroll(int on);
void display_wave(sender_t *sender, sample_t *samples, int length, double range);
+void display_status_on(int on);
+void display_status_limit_scroll(int on);
+void display_status_start(void);
+void display_status_channel(int channel, const char *type, const char *state);
+void display_status_subscriber(const char *number, const char *state);
+void display_status_end(void);
+
void display_iq_init(int samplerate);
void display_iq_on(int on);
void display_iq_limit_scroll(int on);
@@ -44,3 +53,4 @@ void display_spectrum_init(int samplerate);
void display_spectrum_on(int on);
void display_spectrum_limit_scroll(int on);
void display_spectrum(float *samples, int length);
+
diff --git a/src/common/display_status.c b/src/common/display_status.c
new file mode 100644
index 0000000..64ec79c
--- /dev/null
+++ b/src/common/display_status.c
@@ -0,0 +1,147 @@
+/* display status functions
+ *
+ * (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include "sample.h"
+#include "sender.h"
+
+static int status_on = 0;
+static int line_count = 0;
+static int lines_total = 0;
+static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH];
+
+void print_status(int on)
+{
+ int i, j;
+ int w, h;
+
+ get_win_size(&w, &h);
+
+ if (w > MAX_DISPLAY_WIDTH)
+ w = MAX_DISPLAY_WIDTH;
+ h--;
+ if (h > lines_total)
+ h = lines_total;
+
+ printf("\0337\033[H\033[1;37m");
+ for (i = 0; i < h; i++) {
+ j = 0;
+ if (on) {
+ for (j = 0; j < w; j++)
+ putchar(screen[i][j]);
+ } else {
+ for (j = 0; j < w; j++)
+ putchar(' ');
+ }
+ putchar('\n');
+ }
+ printf("\0338"); fflush(stdout);
+}
+
+void display_status_on(int on)
+{
+ if (status_on)
+ print_status(0);
+
+ if (on < 0)
+ status_on = 1 - status_on;
+ else
+ status_on = on;
+
+ if (status_on)
+ print_status(1);
+}
+
+void display_status_limit_scroll(int on)
+{
+ int w, h;
+
+ if (!status_on)
+ return;
+
+ get_win_size(&w, &h);
+
+ printf("\0337");
+ printf("\033[%d;%dr", (on) ? lines_total + 1 : 1, h);
+ printf("\0338");
+}
+
+/* start status display */
+void display_status_start(void)
+{
+ memset(screen, ' ', sizeof(screen));
+ memset(screen[0], '-', sizeof(screen[0]));
+ strncpy(screen[0] + 4, "Channel Status", 14);
+ line_count = 1;
+}
+
+void display_status_channel(int channel, const char *type, const char *state)
+{
+ char line[MAX_DISPLAY_WIDTH];
+
+ /* add empty line after previous channel+subscriber */
+ if (line_count > 1 && line_count < MAX_HEIGHT_STATUS)
+ line_count++;
+
+ if (line_count == MAX_HEIGHT_STATUS)
+ return;
+
+ if (type)
+ snprintf(line, sizeof(line), "Channel: %d Type: %s State: %s", channel, type, state);
+ else
+ snprintf(line, sizeof(line), "Channel: %d State: %s", channel, state);
+ line[sizeof(line) - 1] = '\0';
+ strncpy(screen[line_count++], line, strlen(line));
+}
+
+void display_status_subscriber(const char *number, const char *state)
+{
+ char line[MAX_DISPLAY_WIDTH];
+
+ if (line_count == MAX_HEIGHT_STATUS)
+ return;
+
+ if (state)
+ snprintf(line, sizeof(line), " Subscriber: %s State: %s", number, state);
+ else
+ snprintf(line, sizeof(line), " Subscriber: %s", number);
+ line[sizeof(line) - 1] = '\0';
+ strncpy(screen[line_count++], line, strlen(line));
+}
+
+void display_status_end(void)
+{
+ if (line_count < MAX_HEIGHT_STATUS) {
+ memset(screen[line_count], '-', sizeof(screen[line_count]));
+ line_count++;
+ }
+ /* if last total lines exceed current line count, keep it, so removed lines are overwritten with spaces */
+ if (line_count > lines_total)
+ lines_total = line_count;
+ if (status_on)
+ print_status(1);
+ /* set new total lines */
+ lines_total = line_count;
+}
+
+
diff --git a/src/common/main_common.c b/src/common/main_common.c
index 4eaeaad..32c1a78 100644
--- a/src/common/main_common.c
+++ b/src/common/main_common.c
@@ -166,7 +166,12 @@ void print_hotkeys_common(void)
printf("\n");
printf("Press digits '0'..'9' and then 'd' key to dial towards mobile station\n");
printf("Press 'h' key to hangup.\n");
- printf("Press 'w' key to toggle display of wave form of RX signal.\n");
+ printf("Press 'w' key to toggle display of RX wave form.\n");
+ printf("Press 'c' key to toggle display of channel status.\n");
+#ifdef HAVE_SDR
+ printf("Press 'i' key to toggle display of RX I/Q vector.\n");
+ printf("Press 's' key to toggle display of RX spectrum.\n");
+#endif
}
#define OPT_CHANNEL 1000
@@ -567,18 +572,30 @@ next_char:
display_iq_on(0);
display_spectrum_on(0);
#endif
+ display_status_on(0);
display_wave_on(-1);
goto next_char;
+ case 'c':
+ /* toggle display */
+#ifdef HAVE_SDR
+ display_iq_on(0);
+ display_spectrum_on(0);
+#endif
+ display_wave_on(0);
+ display_status_on(-1);
+ goto next_char;
#ifdef HAVE_SDR
case 'q':
/* toggle display */
display_wave_on(0);
+ display_status_on(0);
display_spectrum_on(0);
display_iq_on(-1);
goto next_char;
case 's':
/* toggle spectrum */
display_wave_on(0);
+ display_status_on(0);
display_iq_on(0);
display_spectrum_on(-1);
goto next_char;
diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c
index b7a5f74..7a92608 100644
--- a/src/nmt/nmt.c
+++ b/src/nmt/nmt.c
@@ -110,12 +110,28 @@ const char *nmt_state_name(enum nmt_state state)
return invalid;
}
+void nmt_display_status(void)
+{
+ sender_t *sender;
+ nmt_t *nmt;
+
+ display_status_start();
+ for (sender = sender_head; sender; sender = sender->next) {
+ nmt = (nmt_t *) sender;
+ display_status_channel(nmt->sender.kanal, chan_type_short_name(nmt->sysinfo.chan_type), nmt_state_name(nmt->state));
+ if (nmt->trans)
+ display_status_subscriber(nmt->trans->subscriber.number, NULL);
+ }
+ display_status_end();
+}
+
static void nmt_new_state(nmt_t *nmt, enum nmt_state new_state)
{
if (nmt->state == new_state)
return;
PDEBUG_CHAN(DNMT, DEBUG_DEBUG, "State change: %s -> %s\n", nmt_state_name(nmt->state), nmt_state_name(new_state));
nmt->state = new_state;
+ nmt_display_status();
}
static struct nmt_channels {
@@ -438,8 +454,8 @@ void nmt_go_idle(nmt_t *nmt)
sms_reset(nmt);
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Entering IDLE state, sending idle frames on %s.\n", chan_type_long_name(nmt->sysinfo.chan_type));
+ nmt->trans = NULL; /* remove transaction before state change, so status is shown correctly */
nmt_new_state(nmt, STATE_IDLE);
- nmt->trans = NULL;
nmt_set_dsp_mode(nmt, DSP_MODE_FRAME);
memset(&nmt->dialing, 0, sizeof(nmt->dialing));
@@ -488,8 +504,8 @@ static void nmt_page(transaction_t *trans, int try)
if (nmt->state != STATE_IDLE && nmt->trans != trans)
continue;
PDEBUG(DNMT, DEBUG_INFO, "Paging on channel %d.\n", sender->kanal);
+ nmt->trans = trans; /* add transaction before state change, so status is shown correctly */
nmt_new_state(nmt, STATE_MT_PAGING);
- nmt->trans = trans;
nmt_set_dsp_mode(nmt, DSP_MODE_FRAME);
nmt->tx_frame_count = 0;
}
@@ -711,8 +727,8 @@ static void rx_idle(nmt_t *nmt, frame_t *frame)
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received roaming seizure from subscriber %c,%s\n", subscr.country, subscr.number);
/* change state */
+ nmt->trans = trans; /* add transaction before state change, so status is shown correctly */
nmt_new_state(nmt, STATE_ROAMING_IDENT);
- nmt->trans = trans;
trans->nmt = nmt;
nmt->rx_frame_count = 0;
nmt->tx_frame_count = 0;
@@ -737,8 +753,8 @@ static void rx_idle(nmt_t *nmt, frame_t *frame)
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received call from subscriber %c,%s%s\n", subscr.country, subscr.number, (subscr.coinbox) ? " (coinbox)" : "");
/* change state */
+ nmt->trans = trans; /* add transaction before state change, so status is shown correctly */
nmt_new_state(nmt, STATE_MO_IDENT);
- nmt->trans = trans;
trans->nmt = nmt;
nmt->rx_frame_count = 0;
nmt->tx_frame_count = 0;