mirror of https://github.com/wb2osz/direwolf.git
APRStt enhancements including new 5 digit suffix format.
This commit is contained in:
parent
d653a534c4
commit
d6bf8102bf
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
- New experimental demodulator. More details later.
|
- New experimental demodulator. More details later.
|
||||||
|
|
||||||
|
- APRStt enhancements including new 5 digit callsign suffix abbreviation and
|
||||||
|
position ambiguity for latitude and longitude in object reports.
|
||||||
|
|
||||||
### Bugs Fixed: ###
|
### Bugs Fixed: ###
|
||||||
|
|
||||||
- "INTERNAL ERROR: dlq_append NULL packet pointer." when using PASSALL.
|
- "INTERNAL ERROR: dlq_append NULL packet pointer." when using PASSALL.
|
||||||
|
|
|
@ -127,7 +127,7 @@ tocalls-symbols :
|
||||||
|
|
||||||
# Separate application to decode raw data.
|
# Separate application to decode raw data.
|
||||||
|
|
||||||
decode_aprs : decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o regex.a misc.a geotranz.a
|
decode_aprs : decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.c regex.a misc.a geotranz.a
|
||||||
$(CC) $(CFLAGS) -DDECAMAIN -o decode_aprs $^
|
$(CC) $(CFLAGS) -DDECAMAIN -o decode_aprs $^
|
||||||
|
|
||||||
|
|
||||||
|
|
59
aclients.c
59
aclients.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2013 John Langner, WB2OSZ
|
// Copyright (C) 2013, 2015 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,11 +28,20 @@
|
||||||
* Description: Establish connection with multiple servers and
|
* Description: Establish connection with multiple servers and
|
||||||
* compare results side by side.
|
* compare results side by side.
|
||||||
*
|
*
|
||||||
* Usage: aclients 8000=AGWPE 8002=DireWolf COM1=D710A
|
* Usage: aclients port1=name1 port2=name2 ...
|
||||||
|
*
|
||||||
|
* Example: aclients 8000=AGWPE 192.168.1.64:8002=DireWolf COM1=D710A
|
||||||
*
|
*
|
||||||
* This will connect to multiple physical or virtual
|
* This will connect to multiple physical or virtual
|
||||||
* TNCs, read packets from them, and display results.
|
* TNCs, read packets from them, and display results.
|
||||||
*
|
*
|
||||||
|
* Each port can have the following forms:
|
||||||
|
*
|
||||||
|
* * host-name:tcp-port
|
||||||
|
* * ip-addr:tcp-port
|
||||||
|
* * tcp-port
|
||||||
|
* * serial port name (e.g. COM1, /dev/ttyS0)
|
||||||
|
*
|
||||||
*---------------------------------------------------------------*/
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +49,6 @@
|
||||||
/*
|
/*
|
||||||
* Native Windows: Use the Winsock interface.
|
* Native Windows: Use the Winsock interface.
|
||||||
* Linux: Use the BSD socket interface.
|
* Linux: Use the BSD socket interface.
|
||||||
* Cygwin: Can use either one.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,14 +164,7 @@ static char * ia_to_text (int Family, void * pAddr, char * pStringBuf, size_t S
|
||||||
* Purpose: Start up multiple client threads listening to different
|
* Purpose: Start up multiple client threads listening to different
|
||||||
* TNCs. Print packets. Tally up statistics.
|
* TNCs. Print packets. Tally up statistics.
|
||||||
*
|
*
|
||||||
* Usage: aclients 8000=AGWPE 8002=DireWolf COM1=D710A
|
* Usage: Described above.
|
||||||
*
|
|
||||||
* Each command line argument is TCP port number or a
|
|
||||||
* serial port name. Follow by = and a text description
|
|
||||||
* of what is connected.
|
|
||||||
*
|
|
||||||
* For now, everything is assumed to be on localhost.
|
|
||||||
* Maybe someday we might recognize host:port=description.
|
|
||||||
*
|
*
|
||||||
*---------------------------------------------------------------*/
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -173,9 +174,17 @@ static char * ia_to_text (int Family, void * pAddr, char * pStringBuf, size_t S
|
||||||
|
|
||||||
static int num_clients;
|
static int num_clients;
|
||||||
|
|
||||||
static char hostname[MAX_CLIENTS][50];
|
static char hostname[MAX_CLIENTS][50]; /* DNS host name or IPv4 address. */
|
||||||
static char port[MAX_CLIENTS][30];
|
/* Some of the code is there for IPv6 but */
|
||||||
static char description[MAX_CLIENTS][50];
|
/* needs more work. */
|
||||||
|
/* Defaults to "localhost" if not specified. */
|
||||||
|
|
||||||
|
static char port[MAX_CLIENTS][30]; /* If it begins with a digit, it is considered */
|
||||||
|
/* a TCP port number at the hostname. */
|
||||||
|
/* Otherwise, we treat it as a serial port name. */
|
||||||
|
|
||||||
|
static char description[MAX_CLIENTS][50]; /* Name used in the output. */
|
||||||
|
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
static HANDLE client_th[MAX_CLIENTS];
|
static HANDLE client_th[MAX_CLIENTS];
|
||||||
|
@ -223,6 +232,8 @@ int main (int argc, char *argv[])
|
||||||
char stemp[100];
|
char stemp[100];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
/* Each command line argument should be of the form "port=description." */
|
||||||
|
|
||||||
strlcpy (stemp, argv[j+1], sizeof(stemp));
|
strlcpy (stemp, argv[j+1], sizeof(stemp));
|
||||||
p = strtok (stemp, "=");
|
p = strtok (stemp, "=");
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
@ -237,6 +248,22 @@ int main (int argc, char *argv[])
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
strlcpy (description[j], p, sizeof(description[j]));
|
strlcpy (description[j], p, sizeof(description[j]));
|
||||||
|
|
||||||
|
/* If the port contains ":" split it into hostname (or addr) and port number. */
|
||||||
|
/* Haven't thought about IPv6 yet. */
|
||||||
|
|
||||||
|
strlcpy (stemp, port[j], sizeof(stemp));
|
||||||
|
|
||||||
|
char *h;
|
||||||
|
|
||||||
|
h = strtok (stemp, ":");
|
||||||
|
if (h != NULL) {
|
||||||
|
p = strtok (NULL, ":");
|
||||||
|
if (p != NULL) {
|
||||||
|
strlcpy (hostname[j], h, sizeof(hostname[j]));
|
||||||
|
strlcpy (port[j], p, sizeof(port[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf ("_WIN32_WINNT = %04x\n", _WIN32_WINNT);
|
//printf ("_WIN32_WINNT = %04x\n", _WIN32_WINNT);
|
||||||
|
@ -253,6 +280,10 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
|
|
||||||
for (j=0; j<num_clients; j++) {
|
for (j=0; j<num_clients; j++) {
|
||||||
|
|
||||||
|
/* If port begins with digit, consider it to be TCP. */
|
||||||
|
/* Otherwise, treat as serial port name. */
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
if (isdigit(port[j][0])) {
|
if (isdigit(port[j][0])) {
|
||||||
client_th[j] = (HANDLE)_beginthreadex (NULL, 0, client_thread_net, (void *)j, 0, NULL);
|
client_th[j] = (HANDLE)_beginthreadex (NULL, 0, client_thread_net, (void *)j, 0, NULL);
|
||||||
|
|
227
aprs_tt.c
227
aprs_tt.c
|
@ -43,7 +43,7 @@
|
||||||
// TODO: clean up terminolgy.
|
// TODO: clean up terminolgy.
|
||||||
// "Message" has a specific meaning in APRS and this is not it.
|
// "Message" has a specific meaning in APRS and this is not it.
|
||||||
// Touch Tone sequence should be appropriate.
|
// Touch Tone sequence should be appropriate.
|
||||||
// What do we call the parts separated by * key? Entry? Field?
|
// What do we call the parts separated by * key? Field.
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -101,6 +101,7 @@ static int parse_fields (char *msg);
|
||||||
static int parse_callsign (char *e);
|
static int parse_callsign (char *e);
|
||||||
static int parse_object_name (char *e);
|
static int parse_object_name (char *e);
|
||||||
static int parse_symbol (char *e);
|
static int parse_symbol (char *e);
|
||||||
|
static int parse_aprstt3_call (char *e);
|
||||||
static int parse_location (char *e);
|
static int parse_location (char *e);
|
||||||
static int parse_comment (char *e);
|
static int parse_comment (char *e);
|
||||||
static int expand_macro (char *e);
|
static int expand_macro (char *e);
|
||||||
|
@ -324,6 +325,7 @@ static double m_latitude; // Set to G_UNKNOWN if not defined.
|
||||||
static int m_ambiguity;
|
static int m_ambiguity;
|
||||||
static char m_comment[200];
|
static char m_comment[200];
|
||||||
static char m_freq[12];
|
static char m_freq[12];
|
||||||
|
static char m_ctcss[8];
|
||||||
static char m_mic_e;
|
static char m_mic_e;
|
||||||
static char m_dao[6];
|
static char m_dao[6];
|
||||||
static int m_ssid; // Default 12 for APRStt user.
|
static int m_ssid; // Default 12 for APRStt user.
|
||||||
|
@ -351,14 +353,15 @@ void aprs_tt_sequence (int chan, char *msg)
|
||||||
* The parse functions will fill these in.
|
* The parse functions will fill these in.
|
||||||
*/
|
*/
|
||||||
strlcpy (m_callsign, "", sizeof(m_callsign));
|
strlcpy (m_callsign, "", sizeof(m_callsign));
|
||||||
m_symtab_or_overlay = '\\';
|
m_symtab_or_overlay = APRSTT_DEFAULT_SYMTAB;
|
||||||
m_symbol_code = 'A';
|
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||||
strlcpy (m_loc_text, "", sizeof(m_loc_text));
|
strlcpy (m_loc_text, "", sizeof(m_loc_text));
|
||||||
m_longitude = G_UNKNOWN;
|
m_longitude = G_UNKNOWN;
|
||||||
m_latitude = G_UNKNOWN;
|
m_latitude = G_UNKNOWN;
|
||||||
m_ambiguity = 0;
|
m_ambiguity = 0;
|
||||||
strlcpy (m_comment, "", sizeof(m_comment));
|
strlcpy (m_comment, "", sizeof(m_comment));
|
||||||
strlcpy (m_freq, "", sizeof(m_freq));
|
strlcpy (m_freq, "", sizeof(m_freq));
|
||||||
|
strlcpy (m_ctcss, "", sizeof(m_ctcss));
|
||||||
m_mic_e = ' ';
|
m_mic_e = ' ';
|
||||||
strlcpy (m_dao, "!T !", sizeof(m_dao)); /* start out unknown */
|
strlcpy (m_dao, "!T !", sizeof(m_dao)); /* start out unknown */
|
||||||
m_ssid = 12;
|
m_ssid = 12;
|
||||||
|
@ -370,8 +373,8 @@ void aprs_tt_sequence (int chan, char *msg)
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("callsign=\"%s\", ssid=%d, symbol=\"%c%c\", freq=\"%s\", comment=\"%s\", lat=%.4f, lon=%.4f, dao=\"%s\"\n",
|
dw_printf ("callsign=\"%s\", ssid=%d, symbol=\"%c%c\", freq=\"%s\", ctcss=\"%s\", comment=\"%s\", lat=%.4f, lon=%.4f, dao=\"%s\"\n",
|
||||||
m_callsign, m_ssid, m_symtab_or_overlay, m_symbol_code, m_freq, m_comment, m_latitude, m_longitude, m_dao);
|
m_callsign, m_ssid, m_symtab_or_overlay, m_symbol_code, m_freq, m_ctcss, m_comment, m_latitude, m_longitude, m_dao);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TT_MAIN
|
#if TT_MAIN
|
||||||
|
@ -386,20 +389,22 @@ void aprs_tt_sequence (int chan, char *msg)
|
||||||
|
|
||||||
err = tt_user_heard (m_callsign, m_ssid, m_symtab_or_overlay, m_symbol_code,
|
err = tt_user_heard (m_callsign, m_ssid, m_symtab_or_overlay, m_symbol_code,
|
||||||
m_loc_text, m_latitude, m_longitude, m_ambiguity,
|
m_loc_text, m_latitude, m_longitude, m_ambiguity,
|
||||||
m_freq, m_comment, m_mic_e, m_dao);
|
m_freq, m_ctcss, m_comment, m_mic_e, m_dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a command / script was supplied, run it now.
|
* If a command / script was supplied, run it now.
|
||||||
* This can do additional processing and provide a custom audible response.
|
* This can do additional processing and provide a custom audible response.
|
||||||
* This is done even for the error case.
|
* This is done only for the success case.
|
||||||
|
* It might be useful to run it for error cases as well but we currently
|
||||||
|
* don't pass in the success / failure code to know the difference.
|
||||||
*/
|
*/
|
||||||
char script_response[1000];
|
char script_response[1000];
|
||||||
|
|
||||||
strlcpy (script_response, "", sizeof(script_response));
|
strlcpy (script_response, "", sizeof(script_response));
|
||||||
|
|
||||||
if (strlen(tt_config.ttcmd) > 0) {
|
if (err == 0 && strlen(tt_config.ttcmd) > 0) {
|
||||||
|
|
||||||
dw_run_cmd (tt_config.ttcmd, 1, script_response, sizeof(script_response));
|
dw_run_cmd (tt_config.ttcmd, 1, script_response, sizeof(script_response));
|
||||||
|
|
||||||
|
@ -409,6 +414,8 @@ void aprs_tt_sequence (int chan, char *msg)
|
||||||
* Send response to user by constructing packet with SPEECH or MORSE as destination.
|
* Send response to user by constructing packet with SPEECH or MORSE as destination.
|
||||||
* Source shouldn't matter because it doesn't get transmitted as AX.25 frame.
|
* Source shouldn't matter because it doesn't get transmitted as AX.25 frame.
|
||||||
* Use high priority queue for consistent timing.
|
* Use high priority queue for consistent timing.
|
||||||
|
*
|
||||||
|
* Anything from script, above, will override other predefined responses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char audible_response[1000];
|
char audible_response[1000];
|
||||||
|
@ -484,25 +491,26 @@ static int parse_fields (char *msg)
|
||||||
case 'A':
|
case 'A':
|
||||||
|
|
||||||
switch (e[1]) {
|
switch (e[1]) {
|
||||||
case 'A':
|
|
||||||
|
case 'A': /* AA object-name */
|
||||||
err = parse_object_name (e);
|
err = parse_object_name (e);
|
||||||
if (err != 0) return (err);
|
if (err != 0) return (err);
|
||||||
break;
|
break;
|
||||||
case 'B':
|
|
||||||
|
case 'B': /* AB symbol */
|
||||||
err = parse_symbol (e);
|
err = parse_symbol (e);
|
||||||
if (err != 0) return (err);
|
if (err != 0) return (err);
|
||||||
break;
|
break;
|
||||||
case 'C':
|
|
||||||
/*
|
case 'C': /* AC new-style-callsign */
|
||||||
* New in 1.2: test for 10 digit callsign.
|
|
||||||
*/
|
err = parse_aprstt3_call (e);
|
||||||
if (tt_call10_to_text(e+2,1,stemp) == 0) {
|
if (err != 0) return (err);
|
||||||
strlcpy(m_callsign, stemp, sizeof(m_callsign));
|
|
||||||
}
|
|
||||||
// TODO1.3: else return (?)
|
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
|
default: /* Traditional style call or suffix */
|
||||||
err = parse_callsign (e);
|
err = parse_callsign (e);
|
||||||
|
if (err != 0) return (err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -674,7 +682,7 @@ static int expand_macro (char *e)
|
||||||
*
|
*
|
||||||
* Name: parse_callsign
|
* Name: parse_callsign
|
||||||
*
|
*
|
||||||
* Purpose: Extract callsign or object name from touch tone message.
|
* Purpose: Extract traditional format callsign or object name from touch tone sequence.
|
||||||
*
|
*
|
||||||
* Inputs: e - An "entry" extracted from a complete
|
* Inputs: e - An "entry" extracted from a complete
|
||||||
* APRStt messsage.
|
* APRStt messsage.
|
||||||
|
@ -685,6 +693,10 @@ static int expand_macro (char *e)
|
||||||
* 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'.
|
||||||
|
* NO! This should be applied only if we
|
||||||
|
* have the default value at this point.
|
||||||
|
* 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.
|
||||||
*
|
*
|
||||||
|
@ -734,7 +746,6 @@ static int checksum_not_ok (char *str, int len, char found)
|
||||||
static int parse_callsign (char *e)
|
static int parse_callsign (char *e)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
//int c_length;
|
|
||||||
char tttemp[40], stemp[30];
|
char tttemp[40], stemp[30];
|
||||||
|
|
||||||
assert (*e == 'A');
|
assert (*e == 'A');
|
||||||
|
@ -772,11 +783,11 @@ static int parse_callsign (char *e)
|
||||||
tttemp[1] = e[len-2];
|
tttemp[1] = e[len-2];
|
||||||
tttemp[2] = '\0';
|
tttemp[2] = '\0';
|
||||||
tt_two_key_to_text (tttemp, 0, stemp);
|
tt_two_key_to_text (tttemp, 0, stemp);
|
||||||
m_symbol_code = 'A';
|
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||||
m_symtab_or_overlay = stemp[0];
|
m_symtab_or_overlay = stemp[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_symbol_code = 'A';
|
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||||
m_symtab_or_overlay = e[len-2];
|
m_symtab_or_overlay = e[len-2];
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -794,7 +805,6 @@ static int parse_callsign (char *e)
|
||||||
return (cs_err);
|
return (cs_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isupper(e[len-2])) {
|
if (isupper(e[len-2])) {
|
||||||
strncpy (tttemp, e+1, len-4);
|
strncpy (tttemp, e+1, len-4);
|
||||||
tttemp[len-4] = '\0';
|
tttemp[len-4] = '\0';
|
||||||
|
@ -804,7 +814,7 @@ static int parse_callsign (char *e)
|
||||||
tttemp[1] = e[len-2];
|
tttemp[1] = e[len-2];
|
||||||
tttemp[2] = '\0';
|
tttemp[2] = '\0';
|
||||||
tt_two_key_to_text (tttemp, 0, stemp);
|
tt_two_key_to_text (tttemp, 0, stemp);
|
||||||
m_symbol_code = 'A';
|
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||||
m_symtab_or_overlay = stemp[0];
|
m_symtab_or_overlay = stemp[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -812,7 +822,7 @@ static int parse_callsign (char *e)
|
||||||
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 = 'A';
|
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||||
m_symtab_or_overlay = e[len-2];
|
m_symtab_or_overlay = e[len-2];
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -823,11 +833,12 @@ static int parse_callsign (char *e)
|
||||||
return (TT_ERROR_INVALID_CALL);
|
return (TT_ERROR_INVALID_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: parse_object_name
|
* Name: parse_object_name
|
||||||
*
|
*
|
||||||
* Purpose: Extract object name from touch tone message.
|
* Purpose: Extract object name from touch tone sequence.
|
||||||
*
|
*
|
||||||
* Inputs: e - An "entry" extracted from a complete
|
* Inputs: e - An "entry" extracted from a complete
|
||||||
* APRStt messsage.
|
* APRStt messsage.
|
||||||
|
@ -883,7 +894,7 @@ static int parse_object_name (char *e)
|
||||||
*
|
*
|
||||||
* Name: parse_symbol
|
* Name: parse_symbol
|
||||||
*
|
*
|
||||||
* Purpose: Extract symbol from touch tone message.
|
* Purpose: Extract symbol from touch tone sequence.
|
||||||
*
|
*
|
||||||
* Inputs: e - An "entry" extracted from a complete
|
* Inputs: e - An "entry" extracted from a complete
|
||||||
* APRStt messsage.
|
* APRStt messsage.
|
||||||
|
@ -973,11 +984,89 @@ static int parse_symbol (char *e)
|
||||||
} /* end parse_oject_name */
|
} /* end parse_oject_name */
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: parse_aprstt3_call
|
||||||
|
*
|
||||||
|
* Purpose: Extract QIKcom-2 / APRStt 3 ten digit call or five digit suffix.
|
||||||
|
*
|
||||||
|
* Inputs: e - An "entry" extracted from a complete
|
||||||
|
* APRStt messsage.
|
||||||
|
* In this case, it should start with "AC".
|
||||||
|
*
|
||||||
|
* Outputs: m_callsign
|
||||||
|
*
|
||||||
|
* Returns: 0 for success or one of the TT_ERROR_... codes.
|
||||||
|
*
|
||||||
|
* Description: We recognize 3 different formats:
|
||||||
|
*
|
||||||
|
* ACxxxxxxxxxx - 10 digit full callsign.
|
||||||
|
*
|
||||||
|
* ACxxxxx - 5 digit suffix. If we can find a corresponding full
|
||||||
|
* callsign, that will be substituted.
|
||||||
|
* Error condition is returned if we can't find one.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int parse_aprstt3_call (char *e)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert (e[0] == 'A');
|
||||||
|
assert (e[1] == 'C');
|
||||||
|
|
||||||
|
if (strlen(e) == 2+10) {
|
||||||
|
char call[12];
|
||||||
|
|
||||||
|
if (tt_call10_to_text(e+2,1,call) == 0) {
|
||||||
|
strlcpy(m_callsign, call, sizeof(m_callsign));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (TT_ERROR_INVALID_CALL); /* Could not convert to text */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strlen(e) == 2+5) {
|
||||||
|
char suffix[8];
|
||||||
|
if (tt_call5_suffix_to_text(e+2,1,suffix) == 0) {
|
||||||
|
|
||||||
|
#if TT_MAIN
|
||||||
|
/* For unit test, use suffix rather than trying lookup. */
|
||||||
|
strlcpy (m_callsign, suffix, sizeof(m_callsign));
|
||||||
|
#else
|
||||||
|
char call[12];
|
||||||
|
|
||||||
|
/* In normal operation, try to find full callsign for the suffix received. */
|
||||||
|
|
||||||
|
if (tt_3char_suffix_search (suffix, call) >= 0) {
|
||||||
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
dw_printf ("Suffix \"%s\" was converted to full callsign \"%s\"\n", suffix, call);
|
||||||
|
|
||||||
|
strlcpy(m_callsign, call, sizeof(m_callsign));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Couldn't find full callsign for suffix \"%s\"\n", suffix);
|
||||||
|
return (TT_ERROR_SUFFIX_NO_CALL); /* Don't know this user. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (TT_ERROR_INVALID_CALL); /* Could not convert to text */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (TT_ERROR_INVALID_CALL); /* Invalid length, not 2+ (10 ir 5) */
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
} /* end parse_aprstt3_call */
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: parse_location
|
* Name: parse_location
|
||||||
*
|
*
|
||||||
* Purpose: Extract location from touch tone message.
|
* Purpose: Extract location from touch tone sequence.
|
||||||
*
|
*
|
||||||
* Inputs: e - An "entry" extracted from a complete
|
* Inputs: e - An "entry" extracted from a complete
|
||||||
* APRStt messsage.
|
* APRStt messsage.
|
||||||
|
@ -985,7 +1074,16 @@ static int parse_symbol (char *e)
|
||||||
*
|
*
|
||||||
* Outputs: m_latitude
|
* Outputs: m_latitude
|
||||||
* m_longitude
|
* m_longitude
|
||||||
* m_dao
|
*
|
||||||
|
* m_dao It should previously be "!T !" to mean unknown or none.
|
||||||
|
* We generally take the first two tones of the field.
|
||||||
|
* For example, "!TB5!" for the standard bearing & range.
|
||||||
|
* The point type is an exception where we use "!Tn !" for
|
||||||
|
* one of ten positions or "!Tnn" for one of a hundred.
|
||||||
|
* If this ever changes, be sure to update corresponding
|
||||||
|
* section in process_comment() in decode_aprs.c
|
||||||
|
*
|
||||||
|
* m_ambiguity
|
||||||
*
|
*
|
||||||
* Returns: 0 for success or one of the TT_ERROR_... codes.
|
* Returns: 0 for success or one of the TT_ERROR_... codes.
|
||||||
*
|
*
|
||||||
|
@ -1001,6 +1099,10 @@ static int parse_symbol (char *e)
|
||||||
* * utm
|
* * utm
|
||||||
* * usng / mgrs
|
* * usng / mgrs
|
||||||
*
|
*
|
||||||
|
* Position ambiguity is also handled here.
|
||||||
|
* Latitude, Longitude, and DAO should not be touched in this case.
|
||||||
|
* We only record a position ambiguity value.
|
||||||
|
*
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Average radius of earth in meters. */
|
/* Average radius of earth in meters. */
|
||||||
|
@ -1009,7 +1111,6 @@ static int parse_symbol (char *e)
|
||||||
|
|
||||||
static int parse_location (char *e)
|
static int parse_location (char *e)
|
||||||
{
|
{
|
||||||
//int len;
|
|
||||||
int ipat;
|
int ipat;
|
||||||
char xstr[VALSTRSIZE], ystr[VALSTRSIZE], zstr[VALSTRSIZE], bstr[VALSTRSIZE], dstr[VALSTRSIZE];
|
char xstr[VALSTRSIZE], ystr[VALSTRSIZE], zstr[VALSTRSIZE], bstr[VALSTRSIZE], dstr[VALSTRSIZE];
|
||||||
double x, y, dist, bearing;
|
double x, y, dist, bearing;
|
||||||
|
@ -1023,14 +1124,6 @@ static int parse_location (char *e)
|
||||||
|
|
||||||
assert (*e == 'B');
|
assert (*e == 'B');
|
||||||
|
|
||||||
m_dao[2] = e[0];
|
|
||||||
m_dao[3] = e[1]; /* Type of location. e.g. !TB6! */
|
|
||||||
/* Will be changed by point types. */
|
|
||||||
|
|
||||||
/* If this ever changes, be sure to update corresponding */
|
|
||||||
/* section in process_comment() in decode_aprs.c */
|
|
||||||
|
|
||||||
//len = strlen(e);
|
|
||||||
|
|
||||||
ipat = find_ttloc_match (e, xstr, ystr, zstr, bstr, dstr, VALSTRSIZE);
|
ipat = find_ttloc_match (e, xstr, ystr, zstr, bstr, dstr, VALSTRSIZE);
|
||||||
if (ipat >= 0) {
|
if (ipat >= 0) {
|
||||||
|
@ -1047,6 +1140,9 @@ static int parse_location (char *e)
|
||||||
/* It's not hardwired to always be B0n or B9nn. */
|
/* It's not hardwired to always be B0n or B9nn. */
|
||||||
/* This is a pretty good approximation. */
|
/* This is a pretty good approximation. */
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
if (strlen(e) == 3) { /* probably B0n --> !Tn ! */
|
if (strlen(e) == 3) { /* probably B0n --> !Tn ! */
|
||||||
m_dao[2] = e[2];
|
m_dao[2] = e[2];
|
||||||
m_dao[3] = ' ';
|
m_dao[3] = ' ';
|
||||||
|
@ -1083,6 +1179,10 @@ static int parse_location (char *e)
|
||||||
|
|
||||||
m_longitude = R2D(lon0 + atan2(sin(bearing) * sin(dist/R) * cos(lat0),
|
m_longitude = R2D(lon0 + atan2(sin(bearing) * sin(dist/R) * cos(lat0),
|
||||||
cos(dist/R) - sin(lat0) * sin(D2R(m_latitude))));
|
cos(dist/R) - sin(lat0) * sin(D2R(m_latitude))));
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTLOC_GRID:
|
case TTLOC_GRID:
|
||||||
|
@ -1108,6 +1208,9 @@ static int parse_location (char *e)
|
||||||
x = atof(xstr);
|
x = atof(xstr);
|
||||||
m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);
|
m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTLOC_UTM:
|
case TTLOC_UTM:
|
||||||
|
@ -1158,6 +1261,9 @@ static int parse_location (char *e)
|
||||||
dw_printf ("Conversion from UTM failed:\n%s\n\n", message);
|
dw_printf ("Conversion from UTM failed:\n%s\n\n", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1207,6 +1313,10 @@ static int parse_location (char *e)
|
||||||
mgrs_error_string (lerr, message);
|
mgrs_error_string (lerr, message);
|
||||||
dw_printf ("Conversion from MGRS/USNG failed:\n%s\n\n", message);
|
dw_printf ("Conversion from MGRS/USNG failed:\n%s\n\n", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTLOC_MHEAD:
|
case TTLOC_MHEAD:
|
||||||
|
@ -1235,6 +1345,10 @@ static int parse_location (char *e)
|
||||||
|
|
||||||
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTLOC_SATSQ:
|
case TTLOC_SATSQ:
|
||||||
|
@ -1253,6 +1367,10 @@ static int parse_location (char *e)
|
||||||
|
|
||||||
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dao[2] = e[0];
|
||||||
|
m_dao[3] = e[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTLOC_AMBIG:
|
case TTLOC_AMBIG:
|
||||||
|
@ -1267,7 +1385,6 @@ static int parse_location (char *e)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert (0);
|
assert (0);
|
||||||
}
|
}
|
||||||
|
@ -1462,6 +1579,9 @@ static int find_ttloc_match (char *e, char *xstr, char *ystr, char *zstr, char *
|
||||||
*
|
*
|
||||||
* Cnnnnnn - Six digit frequency reformatted as nnn.nnnMHz
|
* Cnnnnnn - Six digit frequency reformatted as nnn.nnnMHz
|
||||||
*
|
*
|
||||||
|
* Cnnn - Three digit are for CTCSS tone. Use only integer part
|
||||||
|
* and leading 0 if necessary to make exactly 3 digits.
|
||||||
|
*
|
||||||
* Cttt...tttt - General comment in Multi-press encoding.
|
* Cttt...tttt - General comment in Multi-press encoding.
|
||||||
*
|
*
|
||||||
* CAttt...tttt - New enhanced comment format that can handle all ASCII characters.
|
* CAttt...tttt - New enhanced comment format that can handle all ASCII characters.
|
||||||
|
@ -1501,6 +1621,11 @@ static int parse_comment (char *e)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len == 4 && isdigit(e[1]) && isdigit(e[2]) && isdigit(e[3])) {
|
||||||
|
strlcpy (m_ctcss, e+1, sizeof(m_ctcss));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
tt_multipress_to_text (e+1, 0, m_comment);
|
tt_multipress_to_text (e+1, 0, m_comment);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -1705,9 +1830,6 @@ int dw_run_cmd (char *cmd, int oneline, char *result, size_t resultsiz)
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
// TODO: add this to "make check"
|
|
||||||
|
|
||||||
|
|
||||||
#if TT_MAIN
|
#if TT_MAIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1715,6 +1837,9 @@ int dw_run_cmd (char *cmd, int oneline, char *result, size_t resultsiz)
|
||||||
* It does not maintain any history so abbreviation will not invoke previous full call.
|
* It does not maintain any history so abbreviation will not invoke previous full call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Some examples are derived from http://www.aprs.org/aprstt/aprstt-coding24.txt */
|
||||||
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
char *toneseq; /* Tone sequence in. */
|
char *toneseq; /* Tone sequence in. */
|
||||||
|
|
||||||
|
@ -1728,16 +1853,17 @@ static const struct {
|
||||||
char *dao;
|
char *dao;
|
||||||
} testcases[] = {
|
} testcases[] = {
|
||||||
|
|
||||||
/* Callsigns & abbreviations. */
|
/* Callsigns & abbreviations, traditional */
|
||||||
|
|
||||||
{ "A9A2B42A7A7C71#", "WB4APR", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* WB4APR/7 */
|
{ "A9A2B42A7A7C71#", "WB4APR", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* WB4APR/7 */
|
||||||
{ "A27773#", "277", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* abbreviated form */
|
{ "A27773#", "277", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* abbreviated form */
|
||||||
/* Example in http://www.aprs.org/aprstt/aprstt-coding24.txt has a bad checksum! */
|
|
||||||
/* Bad checksum for "2777". Expected 3 but received 6. */
|
/* Intentionally wrong - Has 6 for checksum when it should be 3. */
|
||||||
{ "A27776#", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Expect error message. */
|
{ "A27776#", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Expect error message. */
|
||||||
|
|
||||||
/* Bad checksum for "2A7A7C7". E xpected 5 but received 1. */
|
/* Example in spec is wrong. checksum should be 5 in this case. */
|
||||||
{ "A2A7A7C71#", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Spelled suffix, overlay, checksum */
|
{ "A2A7A7C71#", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Spelled suffix, overlay, checksum */
|
||||||
|
{ "A2A7A7C75#", "APR", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Spelled suffix, overlay, checksum */
|
||||||
{ "A27773#", "277", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Suffix digits, overlay, checksum */
|
{ "A27773#", "277", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Suffix digits, overlay, checksum */
|
||||||
|
|
||||||
{ "A9A2B26C7D9D71#", "WB2OSZ", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* WB2OSZ/7 numeric overlay */
|
{ "A9A2B26C7D9D71#", "WB2OSZ", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* WB2OSZ/7 numeric overlay */
|
||||||
|
@ -1748,6 +1874,11 @@ static const struct {
|
||||||
|
|
||||||
{ "A277#", "277", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Tactical call "277" no overlay and no checksum */
|
{ "A277#", "277", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* Tactical call "277" no overlay and no checksum */
|
||||||
|
|
||||||
|
/* QIKcom-2 style 10 digit call & 5 digit suffix */
|
||||||
|
|
||||||
|
{ "AC9242771558#", "WB4APR", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" },
|
||||||
|
{ "AC27722#", "APR", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" },
|
||||||
|
|
||||||
/* Locations */
|
/* Locations */
|
||||||
|
|
||||||
{ "B01*A67979#", "679", "12", "7A", "", "", "12.2500", "56.2500", "!T1 !" },
|
{ "B01*A67979#", "679", "12", "7A", "", "", "12.2500", "56.2500", "!T1 !" },
|
||||||
|
@ -1761,6 +1892,8 @@ static const struct {
|
||||||
{ "B21234*A67979#", "679", "12", "7A", "", "", "12.3400", "56.1200", "!TB2!" },
|
{ "B21234*A67979#", "679", "12", "7A", "", "", "12.3400", "56.1200", "!TB2!" },
|
||||||
{ "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" },
|
{ "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" },
|
||||||
|
|
||||||
|
// TODO: should test other coordinate systems.
|
||||||
|
|
||||||
/* Comments */
|
/* Comments */
|
||||||
|
|
||||||
{ "C1", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" },
|
{ "C1", "", "12", "\\A", "", "", "-999999.0000", "-999999.0000", "!T !" },
|
||||||
|
|
10
aprs_tt.h
10
aprs_tt.h
|
@ -80,8 +80,9 @@ struct ttloc_s {
|
||||||
#define TT_ERROR_NO_CALL 9 /* No call or object name included. */
|
#define TT_ERROR_NO_CALL 9 /* No call or object name included. */
|
||||||
#define TT_ERROR_INVALID_MHEAD 10 /* Invalid Maidenhead Locator. */
|
#define TT_ERROR_INVALID_MHEAD 10 /* Invalid Maidenhead Locator. */
|
||||||
#define TT_ERROR_INVALID_SATSQ 11 /* Satellite square must be 4 digits. */
|
#define TT_ERROR_INVALID_SATSQ 11 /* Satellite square must be 4 digits. */
|
||||||
|
#define TT_ERROR_SUFFIX_NO_CALL 12 /* No known callsign for suffix. */
|
||||||
|
|
||||||
#define TT_ERROR_MAXP1 12 /* Number of items above. i.e. Last number plus 1. */
|
#define TT_ERROR_MAXP1 13 /* Number of items above. i.e. Last number plus 1. */
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_C /* Is this being included from config.c? */
|
#if CONFIG_C /* Is this being included from config.c? */
|
||||||
|
@ -100,7 +101,8 @@ static const char *tt_msg_id[TT_ERROR_MAXP1] = {
|
||||||
"INVALID_LOC",
|
"INVALID_LOC",
|
||||||
"NO_CALL",
|
"NO_CALL",
|
||||||
"INVALID_MHEAD",
|
"INVALID_MHEAD",
|
||||||
"INVALID_SATSQ"
|
"INVALID_SATSQ",
|
||||||
|
"SUFFIX_NO_CALL"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -173,6 +175,10 @@ void aprs_tt_button (int chan, char button);
|
||||||
|
|
||||||
#define APRSTT_LOC_DESC_LEN 32 /* Need at least 26 */
|
#define APRSTT_LOC_DESC_LEN 32 /* Need at least 26 */
|
||||||
|
|
||||||
|
#define APRSTT_DEFAULT_SYMTAB '\\'
|
||||||
|
#define APRSTT_DEFAULT_SYMBOL 'A'
|
||||||
|
|
||||||
|
|
||||||
void aprs_tt_dao_to_desc (char *dao, char *str);
|
void aprs_tt_dao_to_desc (char *dao, char *str);
|
||||||
|
|
||||||
void aprs_tt_sequence (int chan, char *msg);
|
void aprs_tt_sequence (int chan, char *msg);
|
||||||
|
|
4
config.c
4
config.c
|
@ -4021,7 +4021,9 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
||||||
b->alt_m = G_UNKNOWN;
|
b->alt_m = G_UNKNOWN;
|
||||||
b->symtab = '/';
|
b->symtab = '/';
|
||||||
b->symbol = '-'; /* house */
|
b->symbol = '-'; /* house */
|
||||||
|
b->freq = G_UNKNOWN;
|
||||||
|
b->tone = G_UNKNOWN;
|
||||||
|
b->offset = G_UNKNOWN;
|
||||||
|
|
||||||
while ((t = split(NULL,0)) != NULL) {
|
while ((t = split(NULL,0)) != NULL) {
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -28,6 +28,11 @@ These dive into more detail for specialized topics or typical usage scenarios.
|
||||||
|
|
||||||
This example illustrates how APRStt can be integrated with other applications such as SARTrack, APRSISCE/32, YAAC, or Xastir.
|
This example illustrates how APRStt can be integrated with other applications such as SARTrack, APRSISCE/32, YAAC, or Xastir.
|
||||||
|
|
||||||
|
- [APRStt Listening Example](APRStt-Listening-Example.pdf)
|
||||||
|
|
||||||
|
WB4APR described a useful application for the [QIKCOM-2 Satallite Transponder](http://www.tapr.org/pipermail/aprssig/2015-November/045035.html).
|
||||||
|
|
||||||
|
Don’t have your own QIKCOM-2 Satellite Transponder? No Problem. You can do the same thing with an ordinary computer and the APRStt gateway built into Dire Wolf. Here’s how.
|
||||||
|
|
||||||
- [Raspberry Pi SDR IGate](Raspberry-Pi-SDR-IGate.pdf)
|
- [Raspberry Pi SDR IGate](Raspberry-Pi-SDR-IGate.pdf)
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -411,62 +411,57 @@ static int cse_spd_data_extension (int course, int speed, char *presult)
|
||||||
*
|
*
|
||||||
* Offset must always be preceded by tone.
|
* Offset must always be preceded by tone.
|
||||||
*
|
*
|
||||||
|
* Resulting formats are all fixed width and have a trailing space:
|
||||||
|
*
|
||||||
|
* "999.999MHz "
|
||||||
|
* "T999 "
|
||||||
|
* "+999 " (10 kHz units)
|
||||||
|
*
|
||||||
|
* Reference: http://www.aprs.org/info/freqspec.txt
|
||||||
|
*
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
typedef struct freq_s {
|
|
||||||
char f[7]; /* format 999.999 */
|
|
||||||
char mhz[3];
|
|
||||||
char space;
|
|
||||||
} freq_t;
|
|
||||||
|
|
||||||
typedef struct to_s {
|
|
||||||
char T;
|
|
||||||
char ttt[3]; /* format 999 (drop fraction) or 'off'. */
|
|
||||||
char space1;
|
|
||||||
char oooo[4]; /* leading sign, 3 digits, tens of KHz. */
|
|
||||||
char space2;
|
|
||||||
} to_t;
|
|
||||||
|
|
||||||
|
|
||||||
static int frequency_spec (float freq, float tone, float offset, char *presult)
|
static int frequency_spec (float freq, float tone, float offset, char *presult)
|
||||||
{
|
{
|
||||||
int result_len = 0;
|
int result_size = 24; // TODO: add as parameter.
|
||||||
|
|
||||||
if (freq != 0) {
|
*presult = '\0';
|
||||||
freq_t *f = (freq_t*)presult;
|
|
||||||
char stemp[12]; /* Frequency should be exactly 7 characters: 999.999 */
|
if (freq > 0) {
|
||||||
/* Offset shouldbe exactly 4 characters: +999 */
|
char stemp[16];
|
||||||
|
|
||||||
/* TODO: Should use letters for > 999.999. */
|
/* TODO: Should use letters for > 999.999. */
|
||||||
snprintf (stemp, sizeof(stemp), "%07.3f", freq);
|
/* For now, just be sure we have proper field width. */
|
||||||
memcpy (f->f, stemp, 7);
|
|
||||||
memcpy (f->mhz, "MHz", 3);
|
if (freq > 999.999) freq = 999.999;
|
||||||
f->space = ' ';
|
|
||||||
result_len = sizeof (freq_t);
|
snprintf (stemp, sizeof(stemp), "%07.3fMHz ", freq);
|
||||||
|
|
||||||
|
strlcpy (presult, stemp, result_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tone != 0 || offset != 0) {
|
if (tone != G_UNKNOWN) {
|
||||||
to_t *to = (to_t*)(presult + result_len);
|
|
||||||
char stemp[12];
|
char stemp[12];
|
||||||
|
|
||||||
to->T = 'T';
|
|
||||||
if (tone == 0) {
|
if (tone == 0) {
|
||||||
memcpy(to->ttt, "off", 3);
|
strlcpy (stemp, "Toff ", sizeof (stemp));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf (stemp, sizeof(stemp), "%03d", (int)tone);
|
snprintf (stemp, sizeof(stemp), "T%03d ", (int)tone);
|
||||||
memcpy (to->ttt, stemp, 3);
|
|
||||||
}
|
|
||||||
to->space1 = ' ';
|
|
||||||
snprintf (stemp, sizeof(stemp), "%+04d", (int)round(offset * 100));
|
|
||||||
memcpy (to->oooo, stemp, 4);
|
|
||||||
to->space2 = ' ';
|
|
||||||
|
|
||||||
result_len += sizeof (to_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (result_len);
|
strlcat (presult, stemp, result_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != G_UNKNOWN) {
|
||||||
|
char stemp[12];
|
||||||
|
|
||||||
|
snprintf (stemp, sizeof(stemp), "%+04d ", (int)round(offset * 100));
|
||||||
|
strlcat (presult, stemp, result_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (strlen(presult));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -800,13 +795,23 @@ int main (int argc, char *argv[])
|
||||||
dw_printf ("%s\n", result);
|
dw_printf ("%s\n", result);
|
||||||
if (strcmp(result, "!4234.61ND07126.47W&PHG7368") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
if (strcmp(result, "!4234.61ND07126.47W&PHG7368") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
/* with freq. */
|
/* with freq & tone. minus offset, no offset, explict simplex. */
|
||||||
|
|
||||||
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
||||||
0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, -0.6, NULL, result, sizeof(result));
|
0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, -0.6, NULL, result, sizeof(result));
|
||||||
dw_printf ("%s\n", result);
|
dw_printf ("%s\n", result);
|
||||||
if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 -060 ") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 -060 ") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
||||||
|
0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, G_UNKNOWN, NULL, result, sizeof(result));
|
||||||
|
dw_printf ("%s\n", result);
|
||||||
|
if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 ") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
||||||
|
0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, 0, NULL, result, sizeof(result));
|
||||||
|
dw_printf ("%s\n", result);
|
||||||
|
if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 +000 ") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
/* with course/speed, freq, and comment! */
|
/* with course/speed, freq, and comment! */
|
||||||
|
|
||||||
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
||||||
|
@ -817,12 +822,17 @@ int main (int argc, char *argv[])
|
||||||
/* Course speed, no tone, + offset */
|
/* Course speed, no tone, + offset */
|
||||||
|
|
||||||
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
|
||||||
0, 0, 0, NULL, 180, 55, 146.955, 0, 0.6, "River flooding", result, sizeof(result));
|
0, 0, 0, NULL, 180, 55, 146.955, G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
|
||||||
dw_printf ("%s\n", result);
|
dw_printf ("%s\n", result);
|
||||||
if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz Toff +060 River flooding") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz +060 River flooding") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
/* Course speed, no tone, + offset + altitude */
|
/* Course speed, no tone, + offset + altitude */
|
||||||
|
|
||||||
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, 12345, 'D', '&',
|
||||||
|
0, 0, 0, NULL, 180, 55, 146.955, G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
|
||||||
|
dw_printf ("%s\n", result);
|
||||||
|
if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz +060 /A=012345River flooding") != 0) { dw_printf ("ERROR! line %d\n", __LINE__); errors++; }
|
||||||
|
|
||||||
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, 12345, 'D', '&',
|
encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, 12345, 'D', '&',
|
||||||
0, 0, 0, NULL, 180, 55, 146.955, 0, 0.6, "River flooding", result, sizeof(result));
|
0, 0, 0, NULL, 180, 55, 146.955, 0, 0.6, "River flooding", result, sizeof(result));
|
||||||
dw_printf ("%s\n", result);
|
dw_printf ("%s\n", result);
|
||||||
|
|
|
@ -569,4 +569,5 @@ C#TTERR INVALID_SYMBOL SPEECH Invalid symbol.
|
||||||
C#TTERR INVALID_LOC SPEECH Invalid location.
|
C#TTERR INVALID_LOC SPEECH Invalid location.
|
||||||
C#TTERR NO_CALL SPEECH No call or object name.
|
C#TTERR NO_CALL SPEECH No call or object name.
|
||||||
C#TTERR SATSQ SPEECH Satellite square must be 4 digits.
|
C#TTERR SATSQ SPEECH Satellite square must be 4 digits.
|
||||||
|
C#TTERR SUFFIX_NO_CALL SPEECH Send full call before using suffix.
|
||||||
C
|
C
|
|
@ -9,12 +9,13 @@ aclients \- Test program for side-by-side TNC performance comparison.
|
||||||
.I tnc ...
|
.I tnc ...
|
||||||
.RS
|
.RS
|
||||||
.P
|
.P
|
||||||
Each \fItnc\fR reference is either a serial port or TCP network port followed by = and a comment.
|
Each \fItnc\fR reference is a port, =, and a description.
|
||||||
.P
|
.P
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBaclients\fR is used to compare how well different TNCs decode AS.25 frames.
|
\fBaclients\fR is used to compare how well different TNCs decode AS.25 frames.
|
||||||
|
The port can be a serial port name, host_name:tcp_port, ip_addr:port, or simply tcp_port.
|
||||||
.P
|
.P
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ None.
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
|
|
||||||
.B aclients /dev/ttyS0=KPC3+ /dev/ttyUSB0=D710A 8000=DireWolf
|
.B aclients /dev/ttyS0=KPC3+ /dev/ttyUSB0=D710A 8000=DireWolf 192.168.1.64:8002=other
|
||||||
.P
|
.P
|
||||||
Serial port /dev/ttyS0 is connected to a KPC3+ with monitor mode turned on.
|
Serial port /dev/ttyS0 is connected to a KPC3+ with monitor mode turned on.
|
||||||
.P
|
.P
|
||||||
|
@ -34,6 +35,8 @@ Serial port /dev/ttyUSB0 is connected to a TM-D710A with monitor mode turned on.
|
||||||
.P
|
.P
|
||||||
The Dire Wolf software TNC is available on network port 8000.
|
The Dire Wolf software TNC is available on network port 8000.
|
||||||
.P
|
.P
|
||||||
|
Some other software TNC is available on network port 8002 on host 192.168.1.64.
|
||||||
|
.P
|
||||||
Packets from each are displayed in columns so it is easy to see how well each decodes
|
Packets from each are displayed in columns so it is easy to see how well each decodes
|
||||||
the received signals.
|
the received signals.
|
||||||
.P
|
.P
|
||||||
|
|
|
@ -652,7 +652,7 @@ static void pick_best_candidate (int chan)
|
||||||
|
|
||||||
/* Clear in preparation for next time. */
|
/* Clear in preparation for next time. */
|
||||||
|
|
||||||
memset (candidate, 0, sizeof(candidate));
|
memset (candidate[chan], 0, sizeof(candidate[chan]));
|
||||||
|
|
||||||
} /* end pick_best_candidate */
|
} /* end pick_best_candidate */
|
||||||
|
|
||||||
|
|
4
rrbb.h
4
rrbb.h
|
@ -51,7 +51,7 @@ rrbb_t rrbb_new (int chan, int subchan, int slice, int is_scrambled, int descram
|
||||||
void rrbb_clear (rrbb_t b, int is_scrambled, int descram_state, int prev_descram);
|
void rrbb_clear (rrbb_t b, int is_scrambled, int descram_state, int prev_descram);
|
||||||
|
|
||||||
|
|
||||||
static __attribute__((always_inline)) void rrbb_append_bit (rrbb_t b, const unsigned char val)
|
static inline /*__attribute__((always_inline))*/ void rrbb_append_bit (rrbb_t b, const unsigned char val)
|
||||||
{
|
{
|
||||||
if (b->len >= MAX_NUM_BITS) {
|
if (b->len >= MAX_NUM_BITS) {
|
||||||
return; /* Silently discard if full. */
|
return; /* Silently discard if full. */
|
||||||
|
@ -60,7 +60,7 @@ static __attribute__((always_inline)) void rrbb_append_bit (rrbb_t b, const unsi
|
||||||
b->len++;
|
b->len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((always_inline)) unsigned char rrbb_get_bit (const rrbb_t b, const int ind)
|
static inline /*__attribute__((always_inline))*/ unsigned char rrbb_get_bit (const rrbb_t b, const int ind)
|
||||||
{
|
{
|
||||||
return (b->fdata[ind]);
|
return (b->fdata[ind]);
|
||||||
}
|
}
|
||||||
|
|
98
tt_text.c
98
tt_text.c
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Module: tt-text.c
|
* Module: tt_text.c
|
||||||
*
|
*
|
||||||
* Purpose: Translate between text and touch tone representation.
|
* Purpose: Translate between text and touch tone representation.
|
||||||
*
|
*
|
||||||
|
@ -1079,6 +1079,102 @@ int tt_call10_to_text (const char *buttons, int quiet, char *text)
|
||||||
} /* end tt_call10_to_text */
|
} /* end tt_call10_to_text */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: tt_call5_suffix_to_text
|
||||||
|
*
|
||||||
|
* Purpose: Convert the 5 digit APRStt 3 style callsign suffix
|
||||||
|
* representation to text.
|
||||||
|
*
|
||||||
|
* Inputs: buttons - Input string.
|
||||||
|
* Should contain exactly 5 digits.
|
||||||
|
*
|
||||||
|
* quiet - True to suppress error messages.
|
||||||
|
*
|
||||||
|
* Outputs: text - Converted to 3 upper case letters and/or digits.
|
||||||
|
*
|
||||||
|
* Returns: Number of errors detected.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int tt_call5_suffix_to_text (const char *buttons, int quiet, char *text)
|
||||||
|
{
|
||||||
|
const char *b;
|
||||||
|
char *t;
|
||||||
|
char c;
|
||||||
|
int packed; /* from last 4 digits */
|
||||||
|
int row, col;
|
||||||
|
int errors = 0;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
t = text;
|
||||||
|
*t = '\0'; /* result */
|
||||||
|
|
||||||
|
/* Validity check. */
|
||||||
|
|
||||||
|
if (strlen(buttons) != 5) {
|
||||||
|
|
||||||
|
if (! quiet) {
|
||||||
|
text_color_set (DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Callsign 3+2 suffix to text: Encoded Callsign \"%s\" must be exactly 5 digits.\n", buttons);
|
||||||
|
}
|
||||||
|
errors++;
|
||||||
|
return (errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (b = buttons; *b != '\0'; b++) {
|
||||||
|
|
||||||
|
if (! isdigit(*b)) {
|
||||||
|
if (! quiet) {
|
||||||
|
text_color_set (DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Callsign 3+2 suffix to text: Encoded Callsign \"%s\" can contain only digits.\n", buttons);
|
||||||
|
}
|
||||||
|
errors++;
|
||||||
|
return (errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packed = atoi(buttons+3);
|
||||||
|
|
||||||
|
for (k = 0; k < 3; k++) {
|
||||||
|
c = buttons[k];
|
||||||
|
|
||||||
|
row = c - '0';
|
||||||
|
col = (packed >> ((2 - k) * 2)) & 3;
|
||||||
|
|
||||||
|
if (row < 0 || row > 9 || col < 0 || col > 3) {
|
||||||
|
text_color_set (DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Callsign 3+2 suffix to text: INTERNAL ERROR %d %d. Should not be here.\n", row, col);
|
||||||
|
errors++;
|
||||||
|
row = 0;
|
||||||
|
col = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (call10encoding[row][col] != 0) {
|
||||||
|
*t++ = call10encoding[row][col];
|
||||||
|
*t = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errors++;
|
||||||
|
if (! quiet) {
|
||||||
|
text_color_set (DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Callsign 3+2 suffix to text: Invalid combination: button %d, position %d.\n", row, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors > 0) {
|
||||||
|
strcpy (text, "");
|
||||||
|
return (errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errors);
|
||||||
|
|
||||||
|
} /* end tt_call5_suffix_to_text */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: tt_mhead_to_text
|
* Name: tt_mhead_to_text
|
||||||
|
|
|
@ -25,6 +25,8 @@ int tt_two_key_to_text (const char *buttons, int quiet, char *text);
|
||||||
|
|
||||||
int tt_call10_to_text (const char *buttons, int quiet, char *text);
|
int tt_call10_to_text (const char *buttons, int quiet, char *text);
|
||||||
|
|
||||||
|
int tt_call5_suffix_to_text (const char *buttons, int quiet, char *text);
|
||||||
|
|
||||||
int tt_mhead_to_text (const char *buttons, int quiet, char *text, size_t textsiz);
|
int tt_mhead_to_text (const char *buttons, int quiet, char *text, size_t textsiz);
|
||||||
|
|
||||||
int tt_satsq_to_text (const char *buttons, int quiet, char *text);
|
int tt_satsq_to_text (const char *buttons, int quiet, char *text);
|
||||||
|
|
122
tt_user.c
122
tt_user.c
|
@ -141,6 +141,9 @@ static struct tt_user_s {
|
||||||
|
|
||||||
char freq[12]; /* Frequency in format 999.999MHz */
|
char freq[12]; /* Frequency in format 999.999MHz */
|
||||||
|
|
||||||
|
char ctcss[5]; /* CTCSS tone. Exactly 3 digits for integer part. */
|
||||||
|
/* For example 74.4 Hz becomes "074". */
|
||||||
|
|
||||||
char comment[MAX_COMMENT_LEN+1]; /* Free form comment from user. */
|
char comment[MAX_COMMENT_LEN+1]; /* Free form comment from user. */
|
||||||
/* Comment sent in final object report includes */
|
/* Comment sent in final object report includes */
|
||||||
/* other information besides this. */
|
/* other information besides this. */
|
||||||
|
@ -215,13 +218,14 @@ void tt_user_init (struct audio_s *p_audio_config, struct tt_config_s *p_tt_conf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: tt_user_search
|
* Name: tt_user_search
|
||||||
*
|
*
|
||||||
* Purpose: Search for user in recent history.
|
* Purpose: Search for user in recent history.
|
||||||
*
|
*
|
||||||
* Inputs: callsign - full or a suffix abbreviation
|
* Inputs: callsign - full or a old style 3 DIGIT suffix abbreviation
|
||||||
* overlay
|
* overlay
|
||||||
*
|
*
|
||||||
* Returns: Handle for refering to table position or -1 if not found.
|
* Returns: Handle for refering to table position or -1 if not found.
|
||||||
|
@ -273,6 +277,51 @@ int tt_user_search (char *callsign, char overlay)
|
||||||
} /* end tt_user_search */
|
} /* end tt_user_search */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: tt_3char_suffix_search
|
||||||
|
*
|
||||||
|
* Purpose: Search for new style 3 CHARACTER (vs. 3 digit) suffix in recent history.
|
||||||
|
*
|
||||||
|
* Inputs: suffix - full or a old style 3 DIGIT suffix abbreviation
|
||||||
|
*
|
||||||
|
* Outputs: callsign - corresponding full callsign or empty string.
|
||||||
|
*
|
||||||
|
* Returns: Handle for refering to table position (>= 0) or -1 if not found.
|
||||||
|
* This happens to be an index into an array but
|
||||||
|
* the implementation could change so the caller should
|
||||||
|
* not make any assumptions.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int tt_3char_suffix_search (char *suffix, char *callsign)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for suffix in list of known calls.
|
||||||
|
*/
|
||||||
|
for (i=0; i<MAX_TT_USERS; i++) {
|
||||||
|
int len = strlen(tt_user[i].callsign);
|
||||||
|
|
||||||
|
if (len >= 3 && len <= 6 && strcmp(tt_user[i].callsign + len - 3, suffix) == 0) {
|
||||||
|
strlcpy (callsign, tt_user[i].callsign, MAX_CALLSIGN_LEN+1);
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not found.
|
||||||
|
*/
|
||||||
|
strlcpy (callsign, "", MAX_CALLSIGN_LEN+1);
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
} /* end tt_3char_suffix_search */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: clear_user
|
* Name: clear_user
|
||||||
|
@ -413,6 +462,7 @@ static void digit_suffix (char *callsign, char *suffix)
|
||||||
* longitude
|
* longitude
|
||||||
* ambiguity
|
* ambiguity
|
||||||
* freq
|
* freq
|
||||||
|
* ctcss
|
||||||
* comment
|
* comment
|
||||||
* mic_e
|
* mic_e
|
||||||
* dao
|
* dao
|
||||||
|
@ -426,7 +476,7 @@ static void digit_suffix (char *callsign, char *suffix)
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude,
|
int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude,
|
||||||
double longitude, int ambiguity, char *freq, char *comment, char mic_e, char *dao)
|
double longitude, int ambiguity, char *freq, char *ctcss, char *comment, char mic_e, char *dao)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -458,8 +508,7 @@ int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *lo
|
||||||
i = find_avail ();
|
i = find_avail ();
|
||||||
|
|
||||||
assert (i >= 0 && i < MAX_TT_USERS);
|
assert (i >= 0 && i < MAX_TT_USERS);
|
||||||
strncpy (tt_user[i].callsign, callsign, MAX_CALLSIGN_LEN);
|
strlcpy (tt_user[i].callsign, callsign, sizeof(tt_user[i].callsign));
|
||||||
tt_user[i].callsign[MAX_CALLSIGN_LEN] = '\0';
|
|
||||||
tt_user[i].count = 1;
|
tt_user[i].count = 1;
|
||||||
tt_user[i].ssid = ssid;
|
tt_user[i].ssid = ssid;
|
||||||
tt_user[i].overlay = overlay;
|
tt_user[i].overlay = overlay;
|
||||||
|
@ -481,14 +530,15 @@ int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *lo
|
||||||
tt_user[i].ambiguity = ambiguity;
|
tt_user[i].ambiguity = ambiguity;
|
||||||
|
|
||||||
strlcpy (tt_user[i].freq, freq, sizeof(tt_user[i].freq));
|
strlcpy (tt_user[i].freq, freq, sizeof(tt_user[i].freq));
|
||||||
strncpy (tt_user[i].comment, comment, MAX_COMMENT_LEN);
|
strlcpy (tt_user[i].ctcss, ctcss, sizeof(tt_user[i].ctcss));
|
||||||
tt_user[i].comment[MAX_COMMENT_LEN] = '\0';
|
strlcpy (tt_user[i].comment, comment, sizeof(tt_user[i].comment));
|
||||||
tt_user[i].mic_e = mic_e;
|
tt_user[i].mic_e = mic_e;
|
||||||
strncpy(tt_user[i].dao, dao, 6);
|
strlcpy(tt_user[i].dao, dao, sizeof(tt_user[i].dao));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
* Known user. Update with any new information.
|
* Known user. Update with any new information.
|
||||||
|
* Keep any old values where not being updated.
|
||||||
*/
|
*/
|
||||||
assert (i >= 0 && i < MAX_TT_USERS);
|
assert (i >= 0 && i < MAX_TT_USERS);
|
||||||
|
|
||||||
|
@ -496,6 +546,13 @@ int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *lo
|
||||||
|
|
||||||
/* Any reason to look at ssid here? */
|
/* Any reason to look at ssid here? */
|
||||||
|
|
||||||
|
/* Update the symbol if not the default. */
|
||||||
|
|
||||||
|
if (overlay != APRSTT_DEFAULT_SYMTAB || symbol != APRSTT_DEFAULT_SYMBOL) {
|
||||||
|
tt_user[i].overlay = overlay;
|
||||||
|
tt_user[i].symbol = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(loc_text) > 0) {
|
if (strlen(loc_text) > 0) {
|
||||||
strlcpy (tt_user[i].loc_text, loc_text, sizeof(tt_user[i].loc_text));
|
strlcpy (tt_user[i].loc_text, loc_text, sizeof(tt_user[i].loc_text));
|
||||||
}
|
}
|
||||||
|
@ -515,17 +572,21 @@ int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *lo
|
||||||
strlcpy (tt_user[i].freq, freq, sizeof(tt_user[i].freq));
|
strlcpy (tt_user[i].freq, freq, sizeof(tt_user[i].freq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctcss[0] != '\0') {
|
||||||
|
strlcpy (tt_user[i].ctcss, ctcss, sizeof(tt_user[i].ctcss));
|
||||||
|
}
|
||||||
|
|
||||||
if (comment[0] != '\0') {
|
if (comment[0] != '\0') {
|
||||||
strncpy (tt_user[i].comment, comment, MAX_COMMENT_LEN);
|
strlcpy (tt_user[i].comment, comment, MAX_COMMENT_LEN);
|
||||||
tt_user[i].comment[MAX_COMMENT_LEN] = '\0';
|
tt_user[i].comment[MAX_COMMENT_LEN] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mic_e != ' ') {
|
if (mic_e != ' ') {
|
||||||
tt_user[i].mic_e = mic_e;
|
tt_user[i].mic_e = mic_e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(dao) > 0) {
|
if (strlen(dao) > 0) {
|
||||||
strncpy(tt_user[i].dao, dao, 6);
|
strlcpy(tt_user[i].dao, dao, sizeof(tt_user[i].dao));
|
||||||
tt_user[i].dao[5] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +843,10 @@ static void xmit_object_report (int i, int first_time)
|
||||||
encode_object (object_name, 0, tt_user[i].last_heard, olat, olong, oambig,
|
encode_object (object_name, 0, tt_user[i].last_heard, olat, olong, oambig,
|
||||||
tt_user[i].overlay, tt_user[i].symbol,
|
tt_user[i].overlay, tt_user[i].symbol,
|
||||||
0,0,0,NULL, G_UNKNOWN, G_UNKNOWN, /* PHGD, Course/Speed */
|
0,0,0,NULL, G_UNKNOWN, G_UNKNOWN, /* PHGD, Course/Speed */
|
||||||
atof(tt_user[i].freq), 0, 0, info_comment, object_info, sizeof(object_info));
|
strlen(tt_user[i].freq) > 0 ? atof(tt_user[i].freq) : G_UNKNOWN,
|
||||||
|
strlen(tt_user[i].ctcss) > 0 ? atof(tt_user[i].ctcss) : G_UNKNOWN,
|
||||||
|
G_UNKNOWN, /* CTCSS */
|
||||||
|
info_comment, object_info, sizeof(object_info));
|
||||||
|
|
||||||
strlcat (stemp, object_info, sizeof(stemp));
|
strlcat (stemp, object_info, sizeof(stemp));
|
||||||
|
|
||||||
|
@ -972,6 +1036,13 @@ static void tt_setenv (int i)
|
||||||
|
|
||||||
setenv ("TTFREQ", tt_user[i].freq, 1);
|
setenv ("TTFREQ", tt_user[i].freq, 1);
|
||||||
|
|
||||||
|
// TODO: Should convert to actual frequency. e.g. 074 becomes 74.4
|
||||||
|
// There is some code for this in decode_aprs.c but not broken out
|
||||||
|
// into a function that we could use from here.
|
||||||
|
// TODO: Document this environment variable after converting.
|
||||||
|
|
||||||
|
setenv ("TTCTCSS", tt_user[i].ctcss, 1);
|
||||||
|
|
||||||
setenv ("TTCOMMENT", tt_user[i].comment, 1);
|
setenv ("TTCOMMENT", tt_user[i].comment, 1);
|
||||||
|
|
||||||
setenv ("TTLOC", tt_user[i].loc_text, 1);
|
setenv ("TTLOC", tt_user[i].loc_text, 1);
|
||||||
|
@ -1006,10 +1077,10 @@ void tt_user_dump (void)
|
||||||
int i;
|
int i;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
||||||
printf ("call ov suf lsthrd xmit nxt cor lat long freq m comment\n");
|
printf ("call ov suf lsthrd xmit nxt cor lat long freq ctcss m comment\n");
|
||||||
for (i=0; i<MAX_TT_USERS; i++) {
|
for (i=0; i<MAX_TT_USERS; i++) {
|
||||||
if (tt_user[i].callsign[0] != '\0') {
|
if (tt_user[i].callsign[0] != '\0') {
|
||||||
printf ("%-6s %c%c %-3s %6d %d %+6d %d %6.2f %7.2f %-10s %c %s\n",
|
printf ("%-6s %c%c %-3s %6d %d %+6d %d %6.2f %7.2f %-10s %-3s %c %s\n",
|
||||||
tt_user[i].callsign,
|
tt_user[i].callsign,
|
||||||
tt_user[i].overlay,
|
tt_user[i].overlay,
|
||||||
tt_user[i].symbol,
|
tt_user[i].symbol,
|
||||||
|
@ -1021,6 +1092,7 @@ void tt_user_dump (void)
|
||||||
tt_user[i].latitude,
|
tt_user[i].latitude,
|
||||||
tt_user[i].longitude,
|
tt_user[i].longitude,
|
||||||
tt_user[i].freq,
|
tt_user[i].freq,
|
||||||
|
tt_user[i].ctcss,
|
||||||
tt_user[i].mic_e,
|
tt_user[i].mic_e,
|
||||||
tt_user[i].comment);
|
tt_user[i].comment);
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1109,7 @@ void tt_user_dump (void)
|
||||||
*
|
*
|
||||||
* Description: Just a smattering, not an organized test.
|
* Description: Just a smattering, not an organized test.
|
||||||
*
|
*
|
||||||
* $ rm a.exe ; gcc -DTT_MAIN -Iregex tt_user.c tt_text.c encode_aprs.c latlong.c textcolor.c ; ./a.exe
|
* $ rm a.exe ; gcc -DTT_MAIN -Iregex tt_user.c tt_text.c encode_aprs.c latlong.c textcolor.c misc.a ; ./a.exe
|
||||||
*
|
*
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -1081,21 +1153,25 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
tt_user_init(&my_audio_config, &my_tt_config);
|
tt_user_init(&my_audio_config, &my_tt_config);
|
||||||
|
|
||||||
tt_user_heard ("TEST1", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
// tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude,
|
||||||
|
// double longitude, int ambiguity, char *freq, char *ctcss, char *comment, char mic_e, char *dao);
|
||||||
|
|
||||||
|
tt_user_heard ("TEST1", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
SLEEP_SEC (1);
|
SLEEP_SEC (1);
|
||||||
tt_user_heard ("TEST2", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
tt_user_heard ("TEST2", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
SLEEP_SEC (1);
|
SLEEP_SEC (1);
|
||||||
tt_user_heard ("TEST3", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
tt_user_heard ("TEST3", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
SLEEP_SEC (1);
|
SLEEP_SEC (1);
|
||||||
tt_user_heard ("TEST4", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
tt_user_heard ("TEST4", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
SLEEP_SEC (1);
|
SLEEP_SEC (1);
|
||||||
tt_user_heard ("WB2OSZ", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
tt_user_heard ("WB2OSZ", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
tt_user_heard ("K2H", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
tt_user_heard ("K2H", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "", ' ', "!T99!");
|
||||||
tt_user_dump ();
|
tt_user_dump ();
|
||||||
|
|
||||||
tt_user_heard ("679", 12, 'J', 'A', 37.25, -71.75, " ", " ", ' ', "!T99!");
|
tt_user_heard ("679", 12, 'J', 'A', "", 37.25, -71.75, 0, "", " ", " ", ' ', "!T99!");
|
||||||
tt_user_heard ("WB2OSZ", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "146.520MHz", "", ' ', "!T99!");
|
tt_user_heard ("WB2OSZ", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "146.520MHz", "", "", ' ', "!T99!");
|
||||||
tt_user_heard ("679", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "Hello, world", '9', "!T99!");
|
tt_user_heard ("WB1GOF", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "146.955MHz", "074", "", ' ', "!T99!");
|
||||||
|
tt_user_heard ("679", 12, 'J', 'A', "", G_UNKNOWN, G_UNKNOWN, 0, "", "", "Hello, world", '9', "!T99!");
|
||||||
tt_user_dump ();
|
tt_user_dump ();
|
||||||
|
|
||||||
for (n=0; n<30; n++) {
|
for (n=0; n<30; n++) {
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
void tt_user_init (struct audio_s *p_audio_config, struct tt_config_s *p);
|
void tt_user_init (struct audio_s *p_audio_config, struct tt_config_s *p);
|
||||||
|
|
||||||
int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude,
|
int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude,
|
||||||
double longitude, int ambiguity, char *freq, char *comment, char mic_e, char *dao);
|
double longitude, int ambiguity, char *freq, char *ctcss, char *comment, char mic_e, char *dao);
|
||||||
|
|
||||||
|
int tt_3char_suffix_search (char *suffix, char *callsign);
|
||||||
|
|
||||||
void tt_user_background (void);
|
void tt_user_background (void);
|
||||||
void tt_user_dump (void);
|
void tt_user_dump (void);
|
Loading…
Reference in New Issue