New "-d d" command line option for APRStt debug.

This commit is contained in:
wb2osz 2020-11-21 20:13:51 -05:00
parent 791982a5e4
commit fdf660a7f1
4 changed files with 113 additions and 23 deletions

View File

@ -122,6 +122,8 @@ m = Monitor heard station list.
f = Packet filtering. f = Packet filtering.
.P .P
x = FX.25 increase verbose level. x = FX.25 increase verbose level.
.P
d = APRStt (DTMF to APRS object conversion).
.RE .RE
.RE .RE
.PD .PD

View File

@ -115,6 +115,8 @@ static int find_ttloc_match (char *e, char *xstr, char *ystr, char *zstr, char *
static void check_result (void); static void check_result (void);
#endif #endif
static int tt_debug = 0;
/*------------------------------------------------------------------ /*------------------------------------------------------------------
* *
@ -122,7 +124,8 @@ static void check_result (void);
* *
* Purpose: Initialize the APRStt gateway at system startup time. * Purpose: Initialize the APRStt gateway at system startup time.
* *
* Inputs: Configuration options gathered by config.c. * Inputs: P - Pointer to configuration options gathered by config.c.
* debug - Debug printing control.
* *
* Global out: Make our own local copy of the structure here. * Global out: Make our own local copy of the structure here.
* *
@ -164,9 +167,10 @@ static struct ttloc_s test_config[] = {
#endif #endif
void aprs_tt_init (struct tt_config_s *p) void aprs_tt_init (struct tt_config_s *p, int debug)
{ {
int c; int c;
tt_debug = debug;
#if TT_MAIN #if TT_MAIN
/* For unit testing. */ /* For unit testing. */
@ -483,7 +487,19 @@ static int parse_fields (char *msg)
//text_color_set(DW_COLOR_DEBUG); //text_color_set(DW_COLOR_DEBUG);
//dw_printf ("parse_fields (%s).\n", msg); //dw_printf ("parse_fields (%s).\n", msg);
strlcpy (stemp, msg, sizeof(stemp)); // Make a copy of msg because strtok corrupts the original.
// While we are at it, remove any blanks.
// This should not happen with DTMF reception but could happen
// in manually crafted strings for testing.
int n = 0;
for (char *m = msg; *m != '\0' && n < sizeof(stemp)-1; m++) {
if (*m != ' ') {
stemp[n++] = *m;
}
}
stemp[n] = '\0';
e = strtok_r (stemp, "*#", &save); e = strtok_r (stemp, "*#", &save);
while (e != NULL) { while (e != NULL) {
@ -551,7 +567,7 @@ static int parse_fields (char *msg)
default: default:
text_color_set(DW_COLOR_ERROR); text_color_set(DW_COLOR_ERROR);
dw_printf ("Field does not start with A, B, C, or digit: \"%s\"\n", msg); dw_printf ("Field does not start with A, B, C, or digit: \"%s\"\n", e);
return (TT_ERROR_D_MSG); return (TT_ERROR_D_MSG);
} }
@ -690,17 +706,15 @@ static int expand_macro (char *e)
* *
* Inputs: e - An "entry" extracted from a complete * Inputs: e - An "entry" extracted from a complete
* APRStt messsage. * APRStt messsage.
* In this case, it should start with "A". * In this case, it should start with "A" then a digit.
* *
* Outputs: m_callsign * Outputs: m_callsign
* *
* m_symtab_or_overlay - Set to 0-9 or A-Z if specified. * m_symtab_or_overlay - Set to 0-9 or A-Z if specified.
* *
* m_symbol_code - Always set to 'A'. * m_symbol_code - Always set to 'A' (Box, DTMF or RFID)
* NO! This should be applied only if we * If you want a different symbol, use the new
* have the default value at this point. * object name format and separate symbol specification.
* The symbol might have been explicitly
* set already and we don't want to overwrite that.
* *
* Returns: 0 for success or one of the TT_ERROR_... codes. * Returns: 0 for success or one of the TT_ERROR_... codes.
* *
@ -752,6 +766,11 @@ static int parse_callsign (char *e)
int len; int len;
char tttemp[40], stemp[30]; char tttemp[40], stemp[30];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("APRStt parse callsign (starts with A then digit): \"%s\"\n", e);
}
assert (*e == 'A'); assert (*e == 'A');
len = strlen(e); len = strlen(e);
@ -762,6 +781,10 @@ static int parse_callsign (char *e)
if (len == 4 && isdigit(e[1]) && isdigit(e[2]) && isdigit(e[3])) { if (len == 4 && isdigit(e[1]) && isdigit(e[2]) && isdigit(e[3])) {
strlcpy (m_callsign, e+1, sizeof(m_callsign)); strlcpy (m_callsign, e+1, sizeof(m_callsign));
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Special case, 3 digit tactical call: \"%s\"\n", m_callsign);
}
return (0); return (0);
} }
@ -779,7 +802,7 @@ static int parse_callsign (char *e)
return (cs_err); return (cs_err);
} }
strncpy (m_callsign, e+1, 3); memcpy (m_callsign, e+1, 3);
m_callsign[3] = '\0'; m_callsign[3] = '\0';
if (len == 7) { if (len == 7) {
@ -789,10 +812,20 @@ static int parse_callsign (char *e)
tt_two_key_to_text (tttemp, 0, stemp); tt_two_key_to_text (tttemp, 0, stemp);
m_symbol_code = APRSTT_DEFAULT_SYMBOL; m_symbol_code = APRSTT_DEFAULT_SYMBOL;
m_symtab_or_overlay = stemp[0]; m_symtab_or_overlay = stemp[0];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Three digit abbreviation1: callsign \"%s\", symbol code '%c (Box DTMF)', overlay '%c', checksum %c\n",
m_callsign, m_symbol_code, m_symtab_or_overlay, e[len-1]);
}
} }
else { else {
m_symbol_code = APRSTT_DEFAULT_SYMBOL; m_symbol_code = APRSTT_DEFAULT_SYMBOL;
m_symtab_or_overlay = e[len-2]; m_symtab_or_overlay = e[len-2];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Three digit abbreviation2: callsign \"%s\", symbol code '%c' (Box DTMF), overlay '%c', checksum %c\n",
m_callsign, m_symbol_code, m_symtab_or_overlay, e[len-1]);
}
} }
return (0); return (0);
} }
@ -810,7 +843,7 @@ static int parse_callsign (char *e)
} }
if (isupper(e[len-2])) { if (isupper(e[len-2])) {
strncpy (tttemp, e+1, len-4); memcpy (tttemp, e+1, len-4);
tttemp[len-4] = '\0'; tttemp[len-4] = '\0';
tt_two_key_to_text (tttemp, 0, m_callsign); tt_two_key_to_text (tttemp, 0, m_callsign);
@ -820,14 +853,24 @@ static int parse_callsign (char *e)
tt_two_key_to_text (tttemp, 0, stemp); tt_two_key_to_text (tttemp, 0, stemp);
m_symbol_code = APRSTT_DEFAULT_SYMBOL; m_symbol_code = APRSTT_DEFAULT_SYMBOL;
m_symtab_or_overlay = stemp[0]; m_symtab_or_overlay = stemp[0];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Callsign in two key format1: callsign \"%s\", symbol code '%c' (Box DTMF), overlay '%c', checksum %c\n",
m_callsign, m_symbol_code, m_symtab_or_overlay, e[len-1]);
}
} }
else { else {
strncpy (tttemp, e+1, len-3); memcpy (tttemp, e+1, len-3);
tttemp[len-3] = '\0'; tttemp[len-3] = '\0';
tt_two_key_to_text (tttemp, 0, m_callsign); tt_two_key_to_text (tttemp, 0, m_callsign);
m_symbol_code = APRSTT_DEFAULT_SYMBOL; m_symbol_code = APRSTT_DEFAULT_SYMBOL;
m_symtab_or_overlay = e[len-2]; m_symtab_or_overlay = e[len-2];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Callsign in two key format2: callsign \"%s\", symbol code '%c' (Box DTMF), overlay '%c', checksum %c\n",
m_callsign, m_symbol_code, m_symtab_or_overlay, e[len-1]);
}
} }
return (0); return (0);
} }
@ -864,9 +907,11 @@ static int parse_callsign (char *e)
static int parse_object_name (char *e) static int parse_object_name (char *e)
{ {
int len; int len;
//int c_length;
//char tttemp[40]; if (tt_debug) {
//char stemp[30]; text_color_set(DW_COLOR_DEBUG);
dw_printf ("APRStt parse object name (starts with AA): \"%s\"\n", e);
}
assert (e[0] == 'A'); assert (e[0] == 'A');
assert (e[1] == 'A'); assert (e[1] == 'A');
@ -882,6 +927,10 @@ static int parse_object_name (char *e)
if (tt_two_key_to_text (e+2, 0, m_callsign) == 0) { if (tt_two_key_to_text (e+2, 0, m_callsign) == 0) {
m_callsign[9] = '\0'; /* truncate to 9 */ m_callsign[9] = '\0'; /* truncate to 9 */
m_ssid = 0; /* No ssid for object name */ m_ssid = 0; /* No ssid for object name */
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Object name in two key format: \"%s\"\n", m_callsign);
}
return (0); return (0);
} }
} }
@ -935,6 +984,11 @@ static int parse_symbol (char *e)
int nn; int nn;
char stemp[10]; char stemp[10];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("APRStt parse symbol (starts with AB): \"%s\"\n", e);
}
assert (e[0] == 'A'); assert (e[0] == 'A');
assert (e[1] == 'B'); assert (e[1] == 'B');
@ -959,12 +1013,22 @@ static int parse_symbol (char *e)
case '1': case '1':
m_symtab_or_overlay = '/'; m_symtab_or_overlay = '/';
m_symbol_code = 32 + nn; m_symbol_code = 32 + nn;
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("symbol code '%c', primary symbol table '%c'\n",
m_symbol_code, m_symtab_or_overlay);
}
return (0); return (0);
break; break;
case '2': case '2':
m_symtab_or_overlay = '\\'; m_symtab_or_overlay = '\\';
m_symbol_code = 32 + nn; m_symbol_code = 32 + nn;
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("symbol code '%c', alternate symbol table '%c'\n",
m_symbol_code, m_symtab_or_overlay);
}
return (0); return (0);
break; break;
@ -973,6 +1037,11 @@ static int parse_symbol (char *e)
if (tt_two_key_to_text (e+5, 0, stemp) == 0) { if (tt_two_key_to_text (e+5, 0, stemp) == 0) {
m_symbol_code = 32 + nn; m_symbol_code = 32 + nn;
m_symtab_or_overlay = stemp[0]; m_symtab_or_overlay = stemp[0];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("symbol code '%c', alternate symbol table with overlay '%c'\n",
m_symbol_code, m_symtab_or_overlay);
}
return (0); return (0);
} }
} }
@ -1018,6 +1087,11 @@ static int parse_aprstt3_call (char *e)
assert (e[0] == 'A'); assert (e[0] == 'A');
assert (e[1] == 'C'); assert (e[1] == 'C');
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("APRStt parse QIKcom-2 / APRStt 3 ten digit call or five digit suffix (starts with AC): \"%s\"\n", e);
}
if (strlen(e) == 2+10) { if (strlen(e) == 2+10) {
char call[12]; char call[12];
@ -1125,6 +1199,11 @@ static int parse_location (char *e)
char mh[20]; char mh[20];
char stemp[32]; char stemp[32];
if (tt_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("APRStt parse location (starts with B): \"%s\"\n", e);
// TODO: more detail later...
}
assert (*e == 'B'); assert (*e == 'B');
@ -1985,7 +2064,7 @@ static void check_result (void)
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
aprs_tt_init (NULL); aprs_tt_init (NULL, 0);
error_count = 0; error_count = 0;

View File

@ -165,7 +165,7 @@ struct tt_config_s {
void aprs_tt_init (struct tt_config_s *p_config); void aprs_tt_init (struct tt_config_s *p_config, int debug);
void aprs_tt_button (int chan, char button); void aprs_tt_button (int chan, char button);

View File

@ -223,6 +223,7 @@ int main (int argc, char *argv[])
int d_h_opt = 0; /* "-d h" option for hamlib debugging. Repeat for more detail */ int d_h_opt = 0; /* "-d h" option for hamlib debugging. Repeat for more detail */
#endif #endif
int d_x_opt = 1; /* "-d x" option for FX.25. Default minimal. Repeat for more detail. -qx to silence. */ int d_x_opt = 1; /* "-d x" option for FX.25. Default minimal. Repeat for more detail. -qx to silence. */
int aprstt_debug = 0; /* "-d d" option for APRStt (think Dtmf) debug. */
int E_tx_opt = 0; /* "-E n" Error rate % for clobbering trasmit frames. */ int E_tx_opt = 0; /* "-E n" Error rate % for clobbering trasmit frames. */
int E_rx_opt = 0; /* "-E Rn" Error rate % for clobbering receive frames. */ int E_rx_opt = 0; /* "-E Rn" Error rate % for clobbering receive frames. */
@ -566,6 +567,7 @@ int main (int argc, char *argv[])
case 'h': d_h_opt++; break; // Hamlib verbose level. case 'h': d_h_opt++; break; // Hamlib verbose level.
#endif #endif
case 'x': d_x_opt++; break; // FX.25 case 'x': d_x_opt++; break; // FX.25
case 'd': aprstt_debug++; break; // APRStt (mnemonic Dtmf)
default: break; default: break;
} }
} }
@ -758,7 +760,7 @@ int main (int argc, char *argv[])
// Will make more precise in afsk demod init. // Will make more precise in afsk demod init.
audio_config.achan[0].mark_freq = 2083; // Actually 2083.3 - logic 1. audio_config.achan[0].mark_freq = 2083; // Actually 2083.3 - logic 1.
audio_config.achan[0].space_freq = 1563; // Actually 1562.5 - logic 0. audio_config.achan[0].space_freq = 1563; // Actually 1562.5 - logic 0.
strlcpy (audio_config.achan[0].profiles, "D", sizeof(audio_config.achan[0].profiles)); strlcpy (audio_config.achan[0].profiles, "A", sizeof(audio_config.achan[0].profiles));
} }
else { else {
audio_config.achan[0].modem_type = MODEM_SCRAMBLE; audio_config.achan[0].modem_type = MODEM_SCRAMBLE;
@ -883,7 +885,7 @@ int main (int argc, char *argv[])
* Initialize the touch tone decoder & APRStt gateway. * Initialize the touch tone decoder & APRStt gateway.
*/ */
dtmf_init (&audio_config, audio_amplitude); dtmf_init (&audio_config, audio_amplitude);
aprs_tt_init (&tt_config); aprs_tt_init (&tt_config, aprstt_debug);
tt_user_init (&audio_config, &tt_config); tt_user_init (&audio_config, &tt_config);
/* /*
@ -1345,18 +1347,24 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
} }
/* /*
* If it came from DTMF decoder, send it to APRStt gateway. * If it came from DTMF decoder (subchan == -1), send it to APRStt gateway.
* Otherwise, it is a candidate for IGate and digipeater. * Otherwise, it is a candidate for IGate and digipeater.
* *
* TODO: It would be useful to have some way to simulate touch tone * It is also useful to have some way to simulate touch tone
* sequences with BEACON sendto=R0 for testing. * sequences with BEACON sendto=R0 for testing.
*/ */
if (subchan == -1) { if (subchan == -1) { // from DTMF decoder
if (tt_config.gateway_enabled && info_len >= 2) { if (tt_config.gateway_enabled && info_len >= 2) {
aprs_tt_sequence (chan, (char*)(pinfo+1)); aprs_tt_sequence (chan, (char*)(pinfo+1));
} }
} }
else if (*pinfo == 't' && info_len >= 2 && tt_config.gateway_enabled) {
// For testing.
// Would be nice to verify it was generated locally,
// not received over the air.
aprs_tt_sequence (chan, (char*)(pinfo+1));
}
else { else {
/* Send to Internet server if option is enabled. */ /* Send to Internet server if option is enabled. */
@ -1487,6 +1495,7 @@ static void usage (char **argv)
dw_printf (" h h = hamlib increase verbose level.\n"); dw_printf (" h h = hamlib increase verbose level.\n");
#endif #endif
dw_printf (" x x = FX.25 increase verbose level.\n"); dw_printf (" x x = FX.25 increase verbose level.\n");
dw_printf (" d d = APRStt (DTMF to APRS object translation).\n");
dw_printf (" -q Quiet (suppress output) options:\n"); dw_printf (" -q Quiet (suppress output) options:\n");
dw_printf (" h h = Heard line with the audio level.\n"); dw_printf (" h h = Heard line with the audio level.\n");
dw_printf (" d d = Decoding of APRS packets.\n"); dw_printf (" d d = Decoding of APRS packets.\n");