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.
|
||||
|
||||
- APRStt enhancements including new 5 digit callsign suffix abbreviation and
|
||||
position ambiguity for latitude and longitude in object reports.
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
||||
- "INTERNAL ERROR: dlq_append NULL packet pointer." when using PASSALL.
|
||||
|
|
|
@ -127,7 +127,7 @@ tocalls-symbols :
|
|||
|
||||
# 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 $^
|
||||
|
||||
|
||||
|
|
59
aclients.c
59
aclients.c
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// 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
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -28,11 +28,20 @@
|
|||
* Description: Establish connection with multiple servers and
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
* TNCs. Print packets. Tally up statistics.
|
||||
*
|
||||
* Usage: aclients 8000=AGWPE 8002=DireWolf COM1=D710A
|
||||
*
|
||||
* 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.
|
||||
* Usage: Described above.
|
||||
*
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
|
@ -173,9 +174,17 @@ static char * ia_to_text (int Family, void * pAddr, char * pStringBuf, size_t S
|
|||
|
||||
static int num_clients;
|
||||
|
||||
static char hostname[MAX_CLIENTS][50];
|
||||
static char port[MAX_CLIENTS][30];
|
||||
static char description[MAX_CLIENTS][50];
|
||||
static char hostname[MAX_CLIENTS][50]; /* DNS host name or IPv4 address. */
|
||||
/* Some of the code is there for IPv6 but */
|
||||
/* 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__
|
||||
static HANDLE client_th[MAX_CLIENTS];
|
||||
|
@ -223,6 +232,8 @@ int main (int argc, char *argv[])
|
|||
char stemp[100];
|
||||
char *p;
|
||||
|
||||
/* Each command line argument should be of the form "port=description." */
|
||||
|
||||
strlcpy (stemp, argv[j+1], sizeof(stemp));
|
||||
p = strtok (stemp, "=");
|
||||
if (p == NULL) {
|
||||
|
@ -237,6 +248,22 @@ int main (int argc, char *argv[])
|
|||
exit (1);
|
||||
}
|
||||
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);
|
||||
|
@ -253,6 +280,10 @@ int main (int argc, char *argv[])
|
|||
|
||||
|
||||
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 (isdigit(port[j][0])) {
|
||||
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.
|
||||
// "Message" has a specific meaning in APRS and this is not it.
|
||||
// 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>
|
||||
|
@ -101,6 +101,7 @@ static int parse_fields (char *msg);
|
|||
static int parse_callsign (char *e);
|
||||
static int parse_object_name (char *e);
|
||||
static int parse_symbol (char *e);
|
||||
static int parse_aprstt3_call (char *e);
|
||||
static int parse_location (char *e);
|
||||
static int parse_comment (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 char m_comment[200];
|
||||
static char m_freq[12];
|
||||
static char m_ctcss[8];
|
||||
static char m_mic_e;
|
||||
static char m_dao[6];
|
||||
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.
|
||||
*/
|
||||
strlcpy (m_callsign, "", sizeof(m_callsign));
|
||||
m_symtab_or_overlay = '\\';
|
||||
m_symbol_code = 'A';
|
||||
m_symtab_or_overlay = APRSTT_DEFAULT_SYMTAB;
|
||||
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||
strlcpy (m_loc_text, "", sizeof(m_loc_text));
|
||||
m_longitude = G_UNKNOWN;
|
||||
m_latitude = G_UNKNOWN;
|
||||
m_ambiguity = 0;
|
||||
strlcpy (m_comment, "", sizeof(m_comment));
|
||||
strlcpy (m_freq, "", sizeof(m_freq));
|
||||
strlcpy (m_ctcss, "", sizeof(m_ctcss));
|
||||
m_mic_e = ' ';
|
||||
strlcpy (m_dao, "!T !", sizeof(m_dao)); /* start out unknown */
|
||||
m_ssid = 12;
|
||||
|
@ -370,8 +373,8 @@ void aprs_tt_sequence (int chan, char *msg)
|
|||
|
||||
#if defined(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",
|
||||
m_callsign, m_ssid, m_symtab_or_overlay, m_symbol_code, m_freq, m_comment, m_latitude, m_longitude, m_dao);
|
||||
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_ctcss, m_comment, m_latitude, m_longitude, m_dao);
|
||||
#endif
|
||||
|
||||
#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,
|
||||
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.
|
||||
* 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];
|
||||
|
||||
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));
|
||||
|
||||
|
@ -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.
|
||||
* Source shouldn't matter because it doesn't get transmitted as AX.25 frame.
|
||||
* Use high priority queue for consistent timing.
|
||||
*
|
||||
* Anything from script, above, will override other predefined responses.
|
||||
*/
|
||||
|
||||
char audible_response[1000];
|
||||
|
@ -484,25 +491,26 @@ static int parse_fields (char *msg)
|
|||
case 'A':
|
||||
|
||||
switch (e[1]) {
|
||||
case 'A':
|
||||
|
||||
case 'A': /* AA object-name */
|
||||
err = parse_object_name (e);
|
||||
if (err != 0) return (err);
|
||||
break;
|
||||
case 'B':
|
||||
|
||||
case 'B': /* AB symbol */
|
||||
err = parse_symbol (e);
|
||||
if (err != 0) return (err);
|
||||
break;
|
||||
case 'C':
|
||||
/*
|
||||
* New in 1.2: test for 10 digit callsign.
|
||||
*/
|
||||
if (tt_call10_to_text(e+2,1,stemp) == 0) {
|
||||
strlcpy(m_callsign, stemp, sizeof(m_callsign));
|
||||
}
|
||||
// TODO1.3: else return (?)
|
||||
|
||||
case 'C': /* AC new-style-callsign */
|
||||
|
||||
err = parse_aprstt3_call (e);
|
||||
if (err != 0) return (err);
|
||||
break;
|
||||
default:
|
||||
|
||||
default: /* Traditional style call or suffix */
|
||||
err = parse_callsign (e);
|
||||
if (err != 0) return (err);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -674,7 +682,7 @@ static int expand_macro (char *e)
|
|||
*
|
||||
* 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
|
||||
* 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_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.
|
||||
*
|
||||
|
@ -734,7 +746,6 @@ static int checksum_not_ok (char *str, int len, char found)
|
|||
static int parse_callsign (char *e)
|
||||
{
|
||||
int len;
|
||||
//int c_length;
|
||||
char tttemp[40], stemp[30];
|
||||
|
||||
assert (*e == 'A');
|
||||
|
@ -772,11 +783,11 @@ static int parse_callsign (char *e)
|
|||
tttemp[1] = e[len-2];
|
||||
tttemp[2] = '\0';
|
||||
tt_two_key_to_text (tttemp, 0, stemp);
|
||||
m_symbol_code = 'A';
|
||||
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||
m_symtab_or_overlay = stemp[0];
|
||||
}
|
||||
else {
|
||||
m_symbol_code = 'A';
|
||||
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||
m_symtab_or_overlay = e[len-2];
|
||||
}
|
||||
return (0);
|
||||
|
@ -794,7 +805,6 @@ static int parse_callsign (char *e)
|
|||
return (cs_err);
|
||||
}
|
||||
|
||||
|
||||
if (isupper(e[len-2])) {
|
||||
strncpy (tttemp, e+1, len-4);
|
||||
tttemp[len-4] = '\0';
|
||||
|
@ -804,7 +814,7 @@ static int parse_callsign (char *e)
|
|||
tttemp[1] = e[len-2];
|
||||
tttemp[2] = '\0';
|
||||
tt_two_key_to_text (tttemp, 0, stemp);
|
||||
m_symbol_code = 'A';
|
||||
m_symbol_code = APRSTT_DEFAULT_SYMBOL;
|
||||
m_symtab_or_overlay = stemp[0];
|
||||
}
|
||||
else {
|
||||
|
@ -812,7 +822,7 @@ static int parse_callsign (char *e)
|
|||
tttemp[len-3] = '\0';
|
||||
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];
|
||||
}
|
||||
return (0);
|
||||
|
@ -823,11 +833,12 @@ static int parse_callsign (char *e)
|
|||
return (TT_ERROR_INVALID_CALL);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
* APRStt messsage.
|
||||
|
@ -883,7 +894,7 @@ static int parse_object_name (char *e)
|
|||
*
|
||||
* 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
|
||||
* APRStt messsage.
|
||||
|
@ -973,11 +984,89 @@ static int parse_symbol (char *e)
|
|||
} /* 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
|
||||
*
|
||||
* Purpose: Extract location from touch tone message.
|
||||
* Purpose: Extract location from touch tone sequence.
|
||||
*
|
||||
* Inputs: e - An "entry" extracted from a complete
|
||||
* APRStt messsage.
|
||||
|
@ -985,7 +1074,16 @@ static int parse_symbol (char *e)
|
|||
*
|
||||
* Outputs: m_latitude
|
||||
* 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.
|
||||
*
|
||||
|
@ -1001,6 +1099,10 @@ static int parse_symbol (char *e)
|
|||
* * utm
|
||||
* * 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. */
|
||||
|
@ -1009,7 +1111,6 @@ static int parse_symbol (char *e)
|
|||
|
||||
static int parse_location (char *e)
|
||||
{
|
||||
//int len;
|
||||
int ipat;
|
||||
char xstr[VALSTRSIZE], ystr[VALSTRSIZE], zstr[VALSTRSIZE], bstr[VALSTRSIZE], dstr[VALSTRSIZE];
|
||||
double x, y, dist, bearing;
|
||||
|
@ -1023,14 +1124,6 @@ static int parse_location (char *e)
|
|||
|
||||
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);
|
||||
if (ipat >= 0) {
|
||||
|
@ -1047,6 +1140,9 @@ static int parse_location (char *e)
|
|||
/* It's not hardwired to always be B0n or B9nn. */
|
||||
/* This is a pretty good approximation. */
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
if (strlen(e) == 3) { /* probably B0n --> !Tn ! */
|
||||
m_dao[2] = e[2];
|
||||
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),
|
||||
cos(dist/R) - sin(lat0) * sin(D2R(m_latitude))));
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
case TTLOC_GRID:
|
||||
|
@ -1108,6 +1208,9 @@ static int parse_location (char *e)
|
|||
x = atof(xstr);
|
||||
m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
case TTLOC_UTM:
|
||||
|
@ -1158,6 +1261,9 @@ static int parse_location (char *e)
|
|||
dw_printf ("Conversion from UTM failed:\n%s\n\n", message);
|
||||
}
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
@ -1207,6 +1313,10 @@ static int parse_location (char *e)
|
|||
mgrs_error_string (lerr, message);
|
||||
dw_printf ("Conversion from MGRS/USNG failed:\n%s\n\n", message);
|
||||
}
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
case TTLOC_MHEAD:
|
||||
|
@ -1235,6 +1345,10 @@ static int parse_location (char *e)
|
|||
|
||||
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
||||
}
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
case TTLOC_SATSQ:
|
||||
|
@ -1253,6 +1367,10 @@ static int parse_location (char *e)
|
|||
|
||||
ll_from_grid_square (mh, &m_latitude, &m_longitude);
|
||||
}
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
||||
break;
|
||||
|
||||
case TTLOC_AMBIG:
|
||||
|
@ -1267,7 +1385,6 @@ static int parse_location (char *e)
|
|||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
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
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* CAttt...tttt - New enhanced comment format that can handle all ASCII characters.
|
||||
|
@ -1501,6 +1621,11 @@ static int parse_comment (char *e)
|
|||
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);
|
||||
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
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
/* Some examples are derived from http://www.aprs.org/aprstt/aprstt-coding24.txt */
|
||||
|
||||
|
||||
static const struct {
|
||||
char *toneseq; /* Tone sequence in. */
|
||||
|
||||
|
@ -1728,16 +1853,17 @@ static const struct {
|
|||
char *dao;
|
||||
} testcases[] = {
|
||||
|
||||
/* Callsigns & abbreviations. */
|
||||
/* Callsigns & abbreviations, traditional */
|
||||
|
||||
{ "A9A2B42A7A7C71#", "WB4APR", "12", "7A", "", "", "-999999.0000", "-999999.0000", "!T !" }, /* WB4APR/7 */
|
||||
{ "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. */
|
||||
|
||||
/* 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 */
|
||||
{ "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 */
|
||||
|
||||
{ "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 */
|
||||
|
||||
/* 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 */
|
||||
|
||||
{ "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!" },
|
||||
{ "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" },
|
||||
|
||||
// TODO: should test other coordinate systems.
|
||||
|
||||
/* Comments */
|
||||
|
||||
{ "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_INVALID_MHEAD 10 /* Invalid Maidenhead Locator. */
|
||||
#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? */
|
||||
|
@ -100,7 +101,8 @@ static const char *tt_msg_id[TT_ERROR_MAXP1] = {
|
|||
"INVALID_LOC",
|
||||
"NO_CALL",
|
||||
"INVALID_MHEAD",
|
||||
"INVALID_SATSQ"
|
||||
"INVALID_SATSQ",
|
||||
"SUFFIX_NO_CALL"
|
||||
};
|
||||
|
||||
#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_DEFAULT_SYMTAB '\\'
|
||||
#define APRSTT_DEFAULT_SYMBOL 'A'
|
||||
|
||||
|
||||
void aprs_tt_dao_to_desc (char *dao, char *str);
|
||||
|
||||
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->symtab = '/';
|
||||
b->symbol = '-'; /* house */
|
||||
|
||||
b->freq = G_UNKNOWN;
|
||||
b->tone = G_UNKNOWN;
|
||||
b->offset = G_UNKNOWN;
|
||||
|
||||
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.
|
||||
|
||||
- [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)
|
||||
|
||||
|
|
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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
int result_len = 0;
|
||||
int result_size = 24; // TODO: add as parameter.
|
||||
|
||||
if (freq != 0) {
|
||||
freq_t *f = (freq_t*)presult;
|
||||
char stemp[12]; /* Frequency should be exactly 7 characters: 999.999 */
|
||||
/* Offset shouldbe exactly 4 characters: +999 */
|
||||
*presult = '\0';
|
||||
|
||||
if (freq > 0) {
|
||||
char stemp[16];
|
||||
|
||||
/* TODO: Should use letters for > 999.999. */
|
||||
snprintf (stemp, sizeof(stemp), "%07.3f", freq);
|
||||
memcpy (f->f, stemp, 7);
|
||||
memcpy (f->mhz, "MHz", 3);
|
||||
f->space = ' ';
|
||||
result_len = sizeof (freq_t);
|
||||
/* For now, just be sure we have proper field width. */
|
||||
|
||||
if (freq > 999.999) freq = 999.999;
|
||||
|
||||
snprintf (stemp, sizeof(stemp), "%07.3fMHz ", freq);
|
||||
|
||||
strlcpy (presult, stemp, result_size);
|
||||
}
|
||||
|
||||
if (tone != 0 || offset != 0) {
|
||||
to_t *to = (to_t*)(presult + result_len);
|
||||
if (tone != G_UNKNOWN) {
|
||||
char stemp[12];
|
||||
|
||||
to->T = 'T';
|
||||
if (tone == 0) {
|
||||
memcpy(to->ttt, "off", 3);
|
||||
strlcpy (stemp, "Toff ", sizeof (stemp));
|
||||
}
|
||||
else {
|
||||
snprintf (stemp, sizeof(stemp), "%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);
|
||||
snprintf (stemp, sizeof(stemp), "T%03d ", (int)tone);
|
||||
}
|
||||
|
||||
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);
|
||||
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', '&',
|
||||
0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, -0.6, NULL, result, sizeof(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++; }
|
||||
|
||||
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! */
|
||||
|
||||
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 */
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
||||
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', '&',
|
||||
0, 0, 0, NULL, 180, 55, 146.955, 0, 0.6, "River flooding", result, sizeof(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 NO_CALL SPEECH No call or object name.
|
||||
C#TTERR SATSQ SPEECH Satellite square must be 4 digits.
|
||||
C#TTERR SUFFIX_NO_CALL SPEECH Send full call before using suffix.
|
||||
C
|
|
@ -9,12 +9,13 @@ aclients \- Test program for side-by-side TNC performance comparison.
|
|||
.I tnc ...
|
||||
.RS
|
||||
.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
|
||||
.RE
|
||||
|
||||
.SH DESCRIPTION
|
||||
\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
|
||||
|
||||
|
||||
|
@ -26,7 +27,7 @@ None.
|
|||
|
||||
.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
|
||||
Serial port /dev/ttyS0 is connected to a KPC3+ with monitor mode turned on.
|
||||
.P
|
||||
|
@ -34,6 +35,8 @@ Serial port /dev/ttyUSB0 is connected to a TM-D710A with monitor mode turned on.
|
|||
.P
|
||||
The Dire Wolf software TNC is available on network port 8000.
|
||||
.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
|
||||
the received signals.
|
||||
.P
|
||||
|
|
|
@ -652,7 +652,7 @@ static void pick_best_candidate (int chan)
|
|||
|
||||
/* Clear in preparation for next time. */
|
||||
|
||||
memset (candidate, 0, sizeof(candidate));
|
||||
memset (candidate[chan], 0, sizeof(candidate[chan]));
|
||||
|
||||
} /* 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);
|
||||
|
||||
|
||||
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) {
|
||||
return; /* Silently discard if full. */
|
||||
|
@ -60,7 +60,7 @@ static __attribute__((always_inline)) void rrbb_append_bit (rrbb_t b, const unsi
|
|||
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]);
|
||||
}
|
||||
|
|
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.
|
||||
*
|
||||
|
@ -1079,6 +1079,102 @@ int tt_call10_to_text (const char *buttons, int quiet, char *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
|
||||
|
|
|
@ -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_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_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 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. */
|
||||
/* Comment sent in final object report includes */
|
||||
/* 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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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 */
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
|
@ -413,6 +462,7 @@ static void digit_suffix (char *callsign, char *suffix)
|
|||
* longitude
|
||||
* ambiguity
|
||||
* freq
|
||||
* ctcss
|
||||
* comment
|
||||
* mic_e
|
||||
* 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,
|
||||
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;
|
||||
|
||||
|
@ -458,8 +508,7 @@ int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *lo
|
|||
i = find_avail ();
|
||||
|
||||
assert (i >= 0 && i < MAX_TT_USERS);
|
||||
strncpy (tt_user[i].callsign, callsign, MAX_CALLSIGN_LEN);
|
||||
tt_user[i].callsign[MAX_CALLSIGN_LEN] = '\0';
|
||||
strlcpy (tt_user[i].callsign, callsign, sizeof(tt_user[i].callsign));
|
||||
tt_user[i].count = 1;
|
||||
tt_user[i].ssid = ssid;
|
||||
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;
|
||||
|
||||
strlcpy (tt_user[i].freq, freq, sizeof(tt_user[i].freq));
|
||||
strncpy (tt_user[i].comment, comment, MAX_COMMENT_LEN);
|
||||
tt_user[i].comment[MAX_COMMENT_LEN] = '\0';
|
||||
strlcpy (tt_user[i].ctcss, ctcss, sizeof(tt_user[i].ctcss));
|
||||
strlcpy (tt_user[i].comment, comment, sizeof(tt_user[i].comment));
|
||||
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 {
|
||||
/*
|
||||
* Known user. Update with any new information.
|
||||
* Keep any old values where not being updated.
|
||||
*/
|
||||
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? */
|
||||
|
||||
/* 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) {
|
||||
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));
|
||||
}
|
||||
|
||||
if (ctcss[0] != '\0') {
|
||||
strlcpy (tt_user[i].ctcss, ctcss, sizeof(tt_user[i].ctcss));
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
if (mic_e != ' ') {
|
||||
tt_user[i].mic_e = mic_e;
|
||||
}
|
||||
|
||||
if (strlen(dao) > 0) {
|
||||
strncpy(tt_user[i].dao, dao, 6);
|
||||
tt_user[i].dao[5] = '\0';
|
||||
strlcpy(tt_user[i].dao, dao, sizeof(tt_user[i].dao));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
tt_user[i].overlay, tt_user[i].symbol,
|
||||
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));
|
||||
|
||||
|
@ -972,6 +1036,13 @@ static void tt_setenv (int i)
|
|||
|
||||
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 ("TTLOC", tt_user[i].loc_text, 1);
|
||||
|
@ -1006,10 +1077,10 @@ void tt_user_dump (void)
|
|||
int i;
|
||||
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++) {
|
||||
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].overlay,
|
||||
tt_user[i].symbol,
|
||||
|
@ -1021,6 +1092,7 @@ void tt_user_dump (void)
|
|||
tt_user[i].latitude,
|
||||
tt_user[i].longitude,
|
||||
tt_user[i].freq,
|
||||
tt_user[i].ctcss,
|
||||
tt_user[i].mic_e,
|
||||
tt_user[i].comment);
|
||||
}
|
||||
|
@ -1037,7 +1109,7 @@ void tt_user_dump (void)
|
|||
*
|
||||
* 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_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
tt_user_heard ("WB2OSZ", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "", ' ', "!T99!");
|
||||
tt_user_heard ("K2H", 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, 0, "", "", "", ' ', "!T99!");
|
||||
tt_user_dump ();
|
||||
|
||||
tt_user_heard ("679", 12, 'J', 'A', 37.25, -71.75, " ", " ", ' ', "!T99!");
|
||||
tt_user_heard ("WB2OSZ", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "146.520MHz", "", ' ', "!T99!");
|
||||
tt_user_heard ("679", 12, 'J', 'A', G_UNKNOWN, G_UNKNOWN, "", "Hello, world", '9', "!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, 0, "146.520MHz", "", "", ' ', "!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 ();
|
||||
|
||||
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);
|
||||
|
||||
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_dump (void);
|
Loading…
Reference in New Issue