mirror of https://github.com/wb2osz/direwolf.git
Generate NMEA waypoint sentences ($PKWDWPL, etc.) for position and object reports.
These can be used by Geosat AvMap or other mapping applications.
This commit is contained in:
parent
283b768125
commit
1f8b330185
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
## Version 1.3 -- Beta Test -- February 2016 ##
|
## Version 1.3 -- Beta Test -- March 2016 ##
|
||||||
|
|
||||||
### New Features: ###
|
### New Features: ###
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ command line option.
|
||||||
|
|
||||||
- When receiving packet with comment of a few hundred characters.
|
- When receiving packet with comment of a few hundred characters.
|
||||||
|
|
||||||
- Address in path, from Internet server. more than 9 characters.
|
- Address in path, from Internet server, more than 9 characters.
|
||||||
|
|
||||||
- "INTERNAL ERROR: dlq_append NULL packet pointer." when using PASSALL.
|
- "INTERNAL ERROR: dlq_append NULL packet pointer." when using PASSALL.
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@ command line option.
|
||||||
- AGW network protocol now works properly for big-endian processors
|
- AGW network protocol now works properly for big-endian processors
|
||||||
such as PowerPC or MIPS.
|
such as PowerPC or MIPS.
|
||||||
|
|
||||||
|
- Packet filtering treated telemetry metadata as messages rather than telemetry.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
## Version 1.2 -- June 2015 ##
|
## Version 1.2 -- June 2015 ##
|
||||||
|
|
|
@ -234,7 +234,7 @@ direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_9600.o hd
|
||||||
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
||||||
gen_tone.o audio.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o morse.o \
|
gen_tone.o audio.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o morse.o \
|
||||||
ptt.o beacon.o encode_aprs.o latlong.o encode_aprs.o latlong.o textcolor.o \
|
ptt.o beacon.o encode_aprs.o latlong.o encode_aprs.o latlong.o textcolor.o \
|
||||||
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o nmea.o serial_port.o log.o telemetry.o \
|
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
||||||
dwgps.o dwgpsnmea.o dwgpsd.o dtime_now.o \
|
dwgps.o dwgpsnmea.o dwgpsd.o dtime_now.o \
|
||||||
misc.a geotranz.a
|
misc.a geotranz.a
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
|
@ -226,7 +226,7 @@ direwolf : direwolf.o aprs_tt.o audio_portaudio.o audio_stats.o ax25_pad.o beaco
|
||||||
encode_aprs.o encode_aprs.o fcs_calc.o fcs_calc.o gen_tone.o \
|
encode_aprs.o encode_aprs.o fcs_calc.o fcs_calc.o gen_tone.o \
|
||||||
geotranz.a hdlc_rec.o hdlc_rec2.o hdlc_send.o igate.o kiss_frame.o \
|
geotranz.a hdlc_rec.o hdlc_rec2.o hdlc_send.o igate.o kiss_frame.o \
|
||||||
kiss.o kissnet.o latlong.o latlong.o log.o morse.o multi_modem.o \
|
kiss.o kissnet.o latlong.o latlong.o log.o morse.o multi_modem.o \
|
||||||
nmea.o serial_port.o pfilter.o ptt.o rdq.o recv.o redecode.o rrbb.o server.o \
|
waypoint.o serial_port.o pfilter.o ptt.o rdq.o recv.o redecode.o rrbb.o server.o \
|
||||||
symbols.o telemetry.o textcolor.o tq.o tt_text.o tt_user.o xmit.o \
|
symbols.o telemetry.o textcolor.o tq.o tt_text.o tt_user.o xmit.o \
|
||||||
dwgps.o dwgpsnmea.o
|
dwgps.o dwgpsnmea.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lpthread $(LDLIBS) -lm
|
$(CC) $(CFLAGS) -o $@ $^ -lpthread $(LDLIBS) -lm
|
||||||
|
|
|
@ -72,7 +72,7 @@ direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_9600.o hd
|
||||||
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
||||||
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o \
|
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o \
|
||||||
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
|
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
|
||||||
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o nmea.o serial_port.o log.o telemetry.o \
|
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
||||||
dwgps.o dwgpsnmea.o dtime_now.o \
|
dwgps.o dwgpsnmea.o dtime_now.o \
|
||||||
dw-icon.o regex.a misc.a geotranz.a
|
dw-icon.o regex.a misc.a geotranz.a
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lwinmm -lws2_32
|
$(CC) $(CFLAGS) -o $@ $^ -lwinmm -lws2_32
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
In the early days of Amateur Packet Radio, it was necessary to use a “Terminal Node Controller” (TNC) with specialized hardware. Those days are gone. You can now get better results at lower cost by connecting your radio to the “soundcard” interface of a computer and using software to decode the signals.
|
In the early days of Amateur Packet Radio, it was necessary to use a “Terminal Node Controller” (TNC) with specialized hardware. Those days are gone. You can now get better results at lower cost by connecting your radio to the “soundcard” interface of a computer and using software to decode the signals.
|
||||||
|
|
||||||
Dire Wolf is a software "soundcard" modem/TNC and [APRS](http://www.aprs.org/) encoder/decoder. It can be used stand-alone to observe APRS traffic, as a digipeater, [APRStt](http://www.aprs.org/aprstt.html) gateway, or Internet Gateway (IGate). It can also be used as a virtual TNC for other applications such as [APRSIS32](http://aprsisce.wikidot.com/), [UI-View32](http://www.ui-view.net/), [Xastir](http://xastir.org/index.php/Main_Page), [APRS-TW](http://aprstw.blandranch.net/), [YAAC](http://www.ka2ddo.org/ka2ddo/YAAC.html), [UISS](http://users.belgacom.net/hamradio/uiss.htm), [Linux AX25](http://www.linux-ax25.org/wiki/Main_Page), [SARTrack](http://www.sartrack.co.nz/index.html), [RMS Express](http://www.winlink.org/RMSExpress), and many others.
|
Dire Wolf is a software "soundcard" modem/TNC and [APRS](http://www.aprs.org/) encoder/decoder. It can be used stand-alone to observe APRS traffic, as a digipeater, [APRStt](http://www.aprs.org/aprstt.html) gateway, or Internet Gateway (IGate). It can also be used as a virtual TNC for other applications such as [APRSIS32](http://aprsisce.wikidot.com/), [UI-View32](http://www.ui-view.net/), [Xastir](http://xastir.org/index.php/Main_Page), [APRS-TW](http://aprstw.blandranch.net/), [YAAC](http://www.ka2ddo.org/ka2ddo/YAAC.html), [UISS](http://users.belgacom.net/hamradio/uiss.htm), [Linux AX25](http://www.linux-ax25.org/wiki/Main_Page), [SARTrack](http://www.sartrack.co.nz/index.html), [RMS Express](http://www.winlink.org/RMSExpress), [BPQ32](http://www.cantab.net/users/john.wiseman/Documents/BPQ32.html), and many others.
|
||||||
|
|
||||||
|
|
||||||
## Features ##
|
## Features ##
|
||||||
|
|
54
config.c
54
config.c
|
@ -753,8 +753,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
|
|
||||||
//strlcpy (p_misc_config->nullmodem, DEFAULT_NULLMODEM, sizeof(p_misc_config->nullmodem));
|
//strlcpy (p_misc_config->nullmodem, DEFAULT_NULLMODEM, sizeof(p_misc_config->nullmodem));
|
||||||
strlcpy (p_misc_config->nullmodem, "", sizeof(p_misc_config->nullmodem));
|
strlcpy (p_misc_config->nullmodem, "", sizeof(p_misc_config->nullmodem));
|
||||||
|
|
||||||
strlcpy (p_misc_config->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
strlcpy (p_misc_config->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
||||||
strlcpy (p_misc_config->nmea_port, "", sizeof(p_misc_config->nmea_port));
|
strlcpy (p_misc_config->waypoint_port, "", sizeof(p_misc_config->waypoint_port));
|
||||||
|
|
||||||
strlcpy (p_misc_config->logdir, "", sizeof(p_misc_config->logdir));
|
strlcpy (p_misc_config->logdir, "", sizeof(p_misc_config->logdir));
|
||||||
|
|
||||||
|
|
||||||
|
@ -1674,10 +1676,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "TXINH") == 0) {
|
else if (strcasecmp(t, "TXINH") == 0) {
|
||||||
int it;
|
|
||||||
char itname[8];
|
char itname[8];
|
||||||
|
|
||||||
it = ICTYPE_TXINH;
|
|
||||||
strlcpy (itname, "TXINH", sizeof(itname));
|
strlcpy (itname, "TXINH", sizeof(itname));
|
||||||
|
|
||||||
t = split(NULL,0);
|
t = split(NULL,0);
|
||||||
|
@ -1701,14 +1701,14 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*t == '-') {
|
if (*t == '-') {
|
||||||
p_audio_config->achan[channel].ictrl[it].gpio = atoi(t+1);
|
p_audio_config->achan[channel].ictrl[ICTYPE_TXINH].gpio = atoi(t+1);
|
||||||
p_audio_config->achan[channel].ictrl[it].invert = 1;
|
p_audio_config->achan[channel].ictrl[ICTYPE_TXINH].invert = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p_audio_config->achan[channel].ictrl[it].gpio = atoi(t);
|
p_audio_config->achan[channel].ictrl[ICTYPE_TXINH].gpio = atoi(t);
|
||||||
p_audio_config->achan[channel].ictrl[it].invert = 0;
|
p_audio_config->achan[channel].ictrl[ICTYPE_TXINH].invert = 0;
|
||||||
}
|
}
|
||||||
p_audio_config->achan[channel].ictrl[it].method = PTT_METHOD_GPIO;
|
p_audio_config->achan[channel].ictrl[ICTYPE_TXINH].method = PTT_METHOD_GPIO;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3828,18 +3828,46 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NMEA - Device name for communication with NMEA device.
|
* WAYPOINT - Generate WPT NMEA sentences for display on map.
|
||||||
* Wasn't documented will probably use WAYPOINT instead.
|
*
|
||||||
|
* WAYPOINT serial-device [ formats ]
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
else if (strcasecmp(t, "nmea") == 0) {
|
else if (strcasecmp(t, "waypoint") == 0) {
|
||||||
t = split(NULL,0);
|
t = split(NULL,0);
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Config file: Missing device name for NMEA port on line %d.\n", line);
|
dw_printf ("Config file: Missing device name for WAYPOINT on line %d.\n", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strlcpy (p_misc_config->nmea_port, t, sizeof(p_misc_config->nmea_port));
|
strlcpy (p_misc_config->waypoint_port, t, sizeof(p_misc_config->waypoint_port));
|
||||||
|
}
|
||||||
|
t = split(NULL,1);
|
||||||
|
if (t != NULL) {
|
||||||
|
for ( ; *t != '\0' ; t++ ) {
|
||||||
|
switch (toupper(*t)) {
|
||||||
|
case 'N':
|
||||||
|
p_misc_config->waypoint_formats |= WPT_FORMAT_NMEA_GENERIC;
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
p_misc_config->waypoint_formats |= WPT_FORMAT_GARMIN;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
p_misc_config->waypoint_formats |= WPT_FORMAT_MAGELLAN;
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
p_misc_config->waypoint_formats |= WPT_FORMAT_KENWOOD;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case ',':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Config file: Invalid output format '%c' for WAYPOINT on line %d.\n", *t, line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
config.h
15
config.h
|
@ -43,6 +43,7 @@ struct misc_config_s {
|
||||||
|
|
||||||
char gpsnmea_port[20]; /* Serial port name for reading NMEA sentences from GPS. */
|
char gpsnmea_port[20]; /* Serial port name for reading NMEA sentences from GPS. */
|
||||||
/* e.g. COM22, /dev/ttyACM0 */
|
/* e.g. COM22, /dev/ttyACM0 */
|
||||||
|
/* Currently no option for setting non-standard speed. */
|
||||||
|
|
||||||
char gpsd_host[20]; /* Host for gpsd server. */
|
char gpsd_host[20]; /* Host for gpsd server. */
|
||||||
/* e.g. localhost, 192.168.1.2 */
|
/* e.g. localhost, 192.168.1.2 */
|
||||||
|
@ -50,9 +51,19 @@ struct misc_config_s {
|
||||||
int gpsd_port; /* Port number for gpsd server. */
|
int gpsd_port; /* Port number for gpsd server. */
|
||||||
/* Default is 2947. */
|
/* Default is 2947. */
|
||||||
|
|
||||||
|
|
||||||
|
char waypoint_port[20]; /* Serial port name for sending NMEA waypoint sentences */
|
||||||
|
/* to a GPS map display or other mapping application. */
|
||||||
/* e.g. COM22, /dev/ttyACM0 */
|
/* e.g. COM22, /dev/ttyACM0 */
|
||||||
char nmea_port[20]; /* Serial port name for NMEA communication with GPS */
|
/* Currently no option for setting non-standard speed. */
|
||||||
/* receiver and/or mapping application. Change this. */
|
|
||||||
|
int waypoint_formats; /* Which sentence formats should be generated? */
|
||||||
|
|
||||||
|
#define WPT_FORMAT_NMEA_GENERIC 0x01 /* N $GPWPT */
|
||||||
|
#define WPT_FORMAT_GARMIN 0x02 /* G $PGRMW */
|
||||||
|
#define WPT_FORMAT_MAGELLAN 0x04 /* M $PMGNWPL */
|
||||||
|
#define WPT_FORMAT_KENWOOD 0x08 /* K $PKWDWPL */
|
||||||
|
|
||||||
|
|
||||||
char logdir[80]; /* Directory for saving activity logs. */
|
char logdir[80]; /* Directory for saving activity logs. */
|
||||||
|
|
||||||
|
|
15
direwolf.c
15
direwolf.c
|
@ -89,7 +89,7 @@
|
||||||
#include "kiss.h"
|
#include "kiss.h"
|
||||||
#include "kissnet.h"
|
#include "kissnet.h"
|
||||||
#include "kiss_frame.h"
|
#include "kiss_frame.h"
|
||||||
#include "nmea.h"
|
#include "waypoint.h"
|
||||||
#include "gen_tone.h"
|
#include "gen_tone.h"
|
||||||
#include "digipeater.h"
|
#include "digipeater.h"
|
||||||
#include "tq.h"
|
#include "tq.h"
|
||||||
|
@ -103,6 +103,7 @@
|
||||||
#include "igate.h"
|
#include "igate.h"
|
||||||
#include "symbols.h"
|
#include "symbols.h"
|
||||||
#include "dwgps.h"
|
#include "dwgps.h"
|
||||||
|
#include "waypoint.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "recv.h"
|
#include "recv.h"
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
@ -162,6 +163,7 @@ static int q_h_opt = 0; /* "-q h" Quiet, suppress the "heard" line with audio
|
||||||
static int q_d_opt = 0; /* "-q d" Quiet, suppress the decoding of APRS packets. */
|
static int q_d_opt = 0; /* "-q d" Quiet, suppress the decoding of APRS packets. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct misc_config_s misc_config;
|
static struct misc_config_s misc_config;
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,8 +238,8 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
text_color_init(t_opt);
|
text_color_init(t_opt);
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
||||||
//dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "K", __DATE__);
|
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "A", __DATE__);
|
||||||
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||||
|
|
||||||
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
|
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
|
||||||
|
@ -451,9 +453,9 @@ int main (int argc, char *argv[])
|
||||||
// separate out gps & waypoints.
|
// separate out gps & waypoints.
|
||||||
|
|
||||||
case 'g': d_g_opt++; break;
|
case 'g': d_g_opt++; break;
|
||||||
|
case 'w': waypoint_set_debug (1); break; // not documented yet.
|
||||||
case 't': d_t_opt++; beacon_tracker_set_debug (d_t_opt); break;
|
case 't': d_t_opt++; beacon_tracker_set_debug (d_t_opt); break;
|
||||||
|
|
||||||
case 'w': nmea_set_debug (1); break; // not documented yet.
|
|
||||||
case 'p': d_p_opt = 1; break; // TODO: packet dump for xmit side.
|
case 'p': d_p_opt = 1; break; // TODO: packet dump for xmit side.
|
||||||
case 'o': d_o_opt++; ptt_set_debug(d_o_opt); break;
|
case 'o': d_o_opt++; ptt_set_debug(d_o_opt); break;
|
||||||
case 'i': d_i_opt++; break;
|
case 'i': d_i_opt++; break;
|
||||||
|
@ -698,7 +700,7 @@ int main (int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
dwgps_init (&misc_config, d_g_opt);
|
dwgps_init (&misc_config, d_g_opt);
|
||||||
|
|
||||||
nmea_init (&misc_config); // TODO: revisit.
|
waypoint_init (&misc_config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create thread for trying to salvage frames with bad FCS.
|
* Create thread for trying to salvage frames with bad FCS.
|
||||||
|
@ -946,7 +948,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
||||||
// Convert to NMEA waypoint sentence if we have a location.
|
// Convert to NMEA waypoint sentence if we have a location.
|
||||||
|
|
||||||
if (A.g_lat != G_UNKNOWN && A.g_lon != G_UNKNOWN) {
|
if (A.g_lat != G_UNKNOWN && A.g_lon != G_UNKNOWN) {
|
||||||
nmea_send_waypoint (strlen(A.g_name) > 0 ? A.g_name : A.g_src,
|
waypoint_send_sentence (strlen(A.g_name) > 0 ? A.g_name : A.g_src,
|
||||||
A.g_lat, A.g_lon, A.g_symbol_table, A.g_symbol_code,
|
A.g_lat, A.g_lon, A.g_symbol_table, A.g_symbol_code,
|
||||||
DW_FEET_TO_METERS(A.g_altitude_ft), A.g_course, DW_MPH_TO_KNOTS(A.g_speed_mph),
|
DW_FEET_TO_METERS(A.g_altitude_ft), A.g_course, DW_MPH_TO_KNOTS(A.g_speed_mph),
|
||||||
A.g_comment);
|
A.g_comment);
|
||||||
|
@ -1026,6 +1028,7 @@ static BOOL cleanup_win (int ctrltype)
|
||||||
dw_printf ("\nQRT\n");
|
dw_printf ("\nQRT\n");
|
||||||
log_term ();
|
log_term ();
|
||||||
ptt_term ();
|
ptt_term ();
|
||||||
|
waypoint_term ();
|
||||||
dwgps_term ();
|
dwgps_term ();
|
||||||
SLEEP_SEC(1);
|
SLEEP_SEC(1);
|
||||||
ExitProcess (0);
|
ExitProcess (0);
|
||||||
|
|
16
dwgpsnmea.c
16
dwgpsnmea.c
|
@ -48,6 +48,7 @@
|
||||||
static int s_debug = 0; /* Enable debug output. */
|
static int s_debug = 0; /* Enable debug output. */
|
||||||
/* See dwgpsnmea_init description for values. */
|
/* See dwgpsnmea_init description for values. */
|
||||||
|
|
||||||
|
static struct misc_config_s *s_save_configp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,6 +110,8 @@ int dwgpsnmea_init (struct misc_config_s *pconfig, int debug)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_debug = debug;
|
s_debug = debug;
|
||||||
|
s_save_configp = pconfig;
|
||||||
|
|
||||||
|
|
||||||
if (s_debug >= 2) {
|
if (s_debug >= 2) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
@ -160,6 +163,19 @@ int dwgpsnmea_init (struct misc_config_s *pconfig, int debug)
|
||||||
} /* end dwgpsnmea_init */
|
} /* end dwgpsnmea_init */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return fd to share if waypoint wants same device. */
|
||||||
|
/* Currently both are fixed speed at 4800. */
|
||||||
|
/* If that ever becomes configurable, that needs to be compared too. */
|
||||||
|
|
||||||
|
MYFDTYPE dwgpsnmea_get_fd(char *wp_port_name, int speed)
|
||||||
|
{
|
||||||
|
if (strcmp(s_save_configp->gpsnmea_port, wp_port_name) == 0 && speed == 4800) {
|
||||||
|
return (s_gpsnmea_port_fd);
|
||||||
|
}
|
||||||
|
return (MYFDERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: read_gpsnmea_thread
|
* Name: read_gpsnmea_thread
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
/* dwgpsnmea.h - For NMEA sentences over serial port */
|
/* dwgpsnmea.h - For reading NMEA sentences over serial port */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,10 +8,13 @@
|
||||||
|
|
||||||
#include "dwgps.h" /* for dwfix_t */
|
#include "dwgps.h" /* for dwfix_t */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "serial_port.h" /* for MYFDTYPE */
|
||||||
|
|
||||||
|
|
||||||
int dwgpsnmea_init (struct misc_config_s *pconfig, int debug);
|
int dwgpsnmea_init (struct misc_config_s *pconfig, int debug);
|
||||||
|
|
||||||
|
MYFDTYPE dwgpsnmea_get_fd(char *wp_port_name, int speed);
|
||||||
|
|
||||||
void dwgpsnmea_term (void);
|
void dwgpsnmea_term (void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +22,7 @@ dwfix_t dwgpsnmea_gprmc (char *sentence, int quiet, double *odlat, double *odlon
|
||||||
|
|
||||||
dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon, float *oalt, int *onsat);
|
dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon, float *oalt, int *onsat);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ p = Packet dump in hexadecimal.
|
||||||
.P
|
.P
|
||||||
g = GPS interface.
|
g = GPS interface.
|
||||||
.P
|
.P
|
||||||
|
W = Waypoints for position or object reports.
|
||||||
|
.P
|
||||||
t = Tracker beacon.
|
t = Tracker beacon.
|
||||||
.P
|
.P
|
||||||
o = Output controls such as PTT and DCD.
|
o = Output controls such as PTT and DCD.
|
||||||
|
|
23
mgn_icon.h
23
mgn_icon.h
|
@ -5,9 +5,18 @@
|
||||||
*
|
*
|
||||||
* Waypoint icon codes for use in the $PMGNWPL sentence.
|
* Waypoint icon codes for use in the $PMGNWPL sentence.
|
||||||
*
|
*
|
||||||
* Derived from Data Transmission Protocol For Magellan Products - version 2.11
|
* Derived from Data Transmission Protocol For Magellan Products - version 2.11, March 2003
|
||||||
|
*
|
||||||
|
* http://www.gpsinformation.org/mag-proto-2-11.pdf
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* That's 13 years ago. There should be something newer available but I can't find it.
|
||||||
|
*
|
||||||
|
* The is based on the newer models at the time. Earlier models had shorter incompatible icon lists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MGN_crossed_square "a"
|
#define MGN_crossed_square "a"
|
||||||
#define MGN_box "b"
|
#define MGN_box "b"
|
||||||
#define MGN_house "c"
|
#define MGN_house "c"
|
||||||
|
@ -110,7 +119,7 @@ static const char mgn_primary_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_default, // E 37 EYEBALL (Eye catcher!)
|
MGN_default, // E 37 EYEBALL (Eye catcher!)
|
||||||
MGN_default, // F 38 Farm Vehicle (tractor)
|
MGN_default, // F 38 Farm Vehicle (tractor)
|
||||||
MGN_default, // G 39 Grid Square (6 digit)
|
MGN_default, // G 39 Grid Square (6 digit)
|
||||||
MGN_default, // H 40 HOTEL (blue bed symbol)
|
MGN_hotel, // H 40 HOTEL (blue bed symbol)
|
||||||
MGN_aerial, // I 41 TcpIp on air network stn
|
MGN_aerial, // I 41 TcpIp on air network stn
|
||||||
MGN_default, // J 42
|
MGN_default, // J 42
|
||||||
MGN_default, // K 43 School
|
MGN_default, // K 43 School
|
||||||
|
@ -150,7 +159,7 @@ static const char mgn_primary_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_aerial, // m 77 Mic-E Repeater
|
MGN_aerial, // m 77 Mic-E Repeater
|
||||||
MGN_default, // n 78 Node (black bulls-eye)
|
MGN_default, // n 78 Node (black bulls-eye)
|
||||||
MGN_default, // o 79 EOC
|
MGN_default, // o 79 EOC
|
||||||
MGN_default, // p 80 ROVER (puppy, or dog)
|
MGN_zoo, // p 80 ROVER (puppy, or dog)
|
||||||
MGN_default, // q 81 GRID SQ shown above 128 m
|
MGN_default, // q 81 GRID SQ shown above 128 m
|
||||||
MGN_aerial, // r 82 Repeater
|
MGN_aerial, // r 82 Repeater
|
||||||
MGN_default, // s 83 SHIP (pwr boat)
|
MGN_default, // s 83 SHIP (pwr boat)
|
||||||
|
@ -202,7 +211,7 @@ static const char mgn_alternate_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_default, // > 30 OVERLAYED CAR
|
MGN_default, // > 30 OVERLAYED CAR
|
||||||
MGN_tourist_info, // ? 31 INFO Kiosk (Blue box with ?)
|
MGN_tourist_info, // ? 31 INFO Kiosk (Blue box with ?)
|
||||||
MGN_default, // @ 32 HURICANE/Trop-Storm
|
MGN_default, // @ 32 HURICANE/Trop-Storm
|
||||||
MGN_default, // A 33 overlayBOX DTMF & RFID & XO
|
MGN_box, // A 33 overlayBOX DTMF & RFID & XO
|
||||||
MGN_default, // B 34 Blwng Snow (& future codes)
|
MGN_default, // B 34 Blwng Snow (& future codes)
|
||||||
MGN_boating, // C 35 Coast Guard
|
MGN_boating, // C 35 Coast Guard
|
||||||
MGN_default, // D 36 Drizzle (proposed APRStt)
|
MGN_default, // D 36 Drizzle (proposed APRStt)
|
||||||
|
@ -215,7 +224,7 @@ static const char mgn_alternate_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_default, // K 43 Kenwood HT (W)
|
MGN_default, // K 43 Kenwood HT (W)
|
||||||
MGN_lighthouse, // L 44 Lighthouse
|
MGN_lighthouse, // L 44 Lighthouse
|
||||||
MGN_default, // M 45 MARS (A=Army,N=Navy,F=AF)
|
MGN_default, // M 45 MARS (A=Army,N=Navy,F=AF)
|
||||||
MGN_nav_aid, // N 46 Navigation Buoy
|
MGN_buoy, // N 46 Navigation Buoy
|
||||||
MGN_airport, // O 47 Rocket
|
MGN_airport, // O 47 Rocket
|
||||||
MGN_default, // P 48 Parking
|
MGN_default, // P 48 Parking
|
||||||
MGN_default, // Q 49 QUAKE
|
MGN_default, // Q 49 QUAKE
|
||||||
|
@ -223,7 +232,7 @@ static const char mgn_alternate_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_aerial, // S 51 Satellite/Pacsat
|
MGN_aerial, // S 51 Satellite/Pacsat
|
||||||
MGN_default, // T 52 Thunderstorm
|
MGN_default, // T 52 Thunderstorm
|
||||||
MGN_default, // U 53 SUNNY
|
MGN_default, // U 53 SUNNY
|
||||||
MGN_default, // V 54 VORTAC Nav Aid
|
MGN_nav_aid, // V 54 VORTAC Nav Aid
|
||||||
MGN_default, // W 55 # NWS site (NWS options)
|
MGN_default, // W 55 # NWS site (NWS options)
|
||||||
MGN_default, // X 56 Pharmacy Rx (Apothicary)
|
MGN_default, // X 56 Pharmacy Rx (Apothicary)
|
||||||
MGN_aerial, // Y 57 Radios and devices
|
MGN_aerial, // Y 57 Radios and devices
|
||||||
|
@ -242,7 +251,7 @@ static const char mgn_alternate_symtab[SYMTAB_SIZE][3] = {
|
||||||
MGN_default, // f 70 Funnel Cloud
|
MGN_default, // f 70 Funnel Cloud
|
||||||
MGN_default, // g 71 Gale Flags
|
MGN_default, // g 71 Gale Flags
|
||||||
MGN_default, // h 72 Store. or HAMFST Hh=HAM store
|
MGN_default, // h 72 Store. or HAMFST Hh=HAM store
|
||||||
MGN_default, // i 73 BOX or points of Interest
|
MGN_box, // i 73 BOX or points of Interest
|
||||||
MGN_default, // j 74 WorkZone (Steam Shovel)
|
MGN_default, // j 74 WorkZone (Steam Shovel)
|
||||||
MGN_default, // k 75 Special Vehicle SUV,ATV,4x4
|
MGN_default, // k 75 Special Vehicle SUV,ATV,4x4
|
||||||
MGN_default, // l 76 Areas (box,circles,etc)
|
MGN_default, // l 76 Areas (box,circles,etc)
|
||||||
|
|
465
nmea.c
465
nmea.c
|
@ -1,465 +0,0 @@
|
||||||
//
|
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2014, 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
|
|
||||||
// the Free Software Foundation, either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//#define DEBUG 1
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: rename this to waypoint & integrate.
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Module: nmea.c
|
|
||||||
*
|
|
||||||
* Purpose: Receive NMEA sentences from a GPS receiver.
|
|
||||||
* Send NMEA waypoint sentences to GPS display or mapping application.
|
|
||||||
*
|
|
||||||
*---------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#define __USE_XOPEN2KXSI 1
|
|
||||||
#define __USE_XOPEN 1
|
|
||||||
//#define __USE_POSIX 1
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/errno.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
char *strsep(char **stringp, const char *delim);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "direwolf.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "ax25_pad.h"
|
|
||||||
#include "textcolor.h"
|
|
||||||
//#include "xmit.h"
|
|
||||||
#include "latlong.h"
|
|
||||||
#include "nmea.h"
|
|
||||||
#include "grm_sym.h" /* Garmin symbols */
|
|
||||||
#include "mgn_icon.h" /* Magellan icons */
|
|
||||||
#include "serial_port.h"
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: receive buffer... static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
|
|
||||||
|
|
||||||
static MYFDTYPE nmea_port_fd = MYFDERROR;
|
|
||||||
|
|
||||||
static void nmea_send_sentence (char *sent);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//static void nmea_parse_gps (char *sentence);
|
|
||||||
|
|
||||||
|
|
||||||
static int nmea_debug = 0; /* Print information flowing from and to attached device. */
|
|
||||||
|
|
||||||
void nmea_set_debug (int n)
|
|
||||||
{
|
|
||||||
nmea_debug = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Name: nmea_init
|
|
||||||
*
|
|
||||||
* Purpose: Initialization for NMEA communication port.
|
|
||||||
*
|
|
||||||
* Inputs: mc->nmea_port - name of serial port.
|
|
||||||
*
|
|
||||||
* Global output: nmea_port_fd
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Description: (1) Open serial port device.
|
|
||||||
*
|
|
||||||
*---------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
void nmea_init (struct misc_config_s *mc)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open serial port connection.
|
|
||||||
* 4800 baud is standard for GPS.
|
|
||||||
* Should add an option to allow changing someday.
|
|
||||||
*/
|
|
||||||
if (strlen(mc->nmea_port) > 0) {
|
|
||||||
|
|
||||||
nmea_port_fd = serial_port_open (mc->nmea_port, 4800);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
text_color_set (DW_COLOR_DEBUG);
|
|
||||||
|
|
||||||
dw_printf ("end of nmea_init: nmea_port_fd = %d\n", nmea_port_fd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Name: append_checksum
|
|
||||||
*
|
|
||||||
* Purpose: Append checksum to the sentence.
|
|
||||||
*
|
|
||||||
* In/out: sentence - NMEA sentence beginning with '$'.
|
|
||||||
*
|
|
||||||
* Description: Checksum is exclusive of characters except leading '$'.
|
|
||||||
* We append '*' and an upper case two hexadecimal value.
|
|
||||||
*
|
|
||||||
*--------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void append_checksum (char *sentence)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int cs;
|
|
||||||
|
|
||||||
assert (sentence[0] == '$');
|
|
||||||
|
|
||||||
cs = 0;
|
|
||||||
for (p = sentence+1; *p != '\0'; p++) {
|
|
||||||
cs ^= *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (p, "*%02X", cs & 0xff);
|
|
||||||
|
|
||||||
// Add crlf too?
|
|
||||||
|
|
||||||
} /* end append_checksum */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Name: nema_send_waypoint
|
|
||||||
*
|
|
||||||
* Purpose: Convert APRS position or object into NMEA waypoint sentence
|
|
||||||
* for use by a GPS display or other mapping application.
|
|
||||||
*
|
|
||||||
* Inputs: wname_in - Name of waypoint.
|
|
||||||
* dlat - Latitude.
|
|
||||||
* dlong - Longitude.
|
|
||||||
* symtab - Symbol table or overlay character.
|
|
||||||
* symbol - Symbol code.
|
|
||||||
* alt - Altitude in meters or G_UNKOWN.
|
|
||||||
* course - Course in degrees or ??? for unknown.
|
|
||||||
* speed - Speed in knots ?? or ??
|
|
||||||
* comment - Description or message.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Description: Currently we send multiple styles. Maybe someday there might
|
|
||||||
* be an option to send a selected subset.
|
|
||||||
*
|
|
||||||
* $GPWPL - Generic with only location and name.
|
|
||||||
* $PGRMW - Garmin, adds altitude, symbol, and comment
|
|
||||||
* to previously named waypoint.
|
|
||||||
* $PMGNWPL - Magellan, more complete for stationary objects.
|
|
||||||
* $PKWDWPL - Kenwood with APRS style symbol but missing comment.
|
|
||||||
*
|
|
||||||
*--------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
void nmea_send_waypoint (char *wname_in, double dlat, double dlong, char symtab, char symbol,
|
|
||||||
float alt, float course, float speed, char *comment)
|
|
||||||
{
|
|
||||||
char wname[12]; /* Waypoint name. Any , or * removed. */
|
|
||||||
char slat[12]; /* DDMM.mmmm */
|
|
||||||
char slat_ns[2]; /* N or S */
|
|
||||||
char slong[12]; /* DDDMM.mmmm */
|
|
||||||
char slong_ew[2]; /* E or W */
|
|
||||||
char sentence[500];
|
|
||||||
char salt[12]; /* altitude as string, empty if unknown */
|
|
||||||
char sspeed[12]; /* speed as string, empty if unknown */
|
|
||||||
char scourse[12]; /* course as string, empty if unknown */
|
|
||||||
int grm_sym; /* Garmin symbol code. */
|
|
||||||
char sicon[5]; /* Magellan icon string */
|
|
||||||
char stime[8];
|
|
||||||
char sdate[8];
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Remove any comma from name.
|
|
||||||
|
|
||||||
// TODO: remove any , or * from comment.
|
|
||||||
|
|
||||||
strcpy (wname, wname_in);
|
|
||||||
for (p=wname; *p != '\0'; p++) {
|
|
||||||
if (*p == ',') *p = ' ';
|
|
||||||
if (*p == '*') *p = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert position to character form.
|
|
||||||
|
|
||||||
latitude_to_nmea (dlat, slat, slat_ns);
|
|
||||||
longitude_to_nmea (dlong, slong, slong_ew);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic.
|
|
||||||
*
|
|
||||||
* $GPWPL,ddmm.mmmm,ns,dddmm.mmmm,ew,wname*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
* ddmm.mmmm,ns is latitude
|
|
||||||
* dddmm.mmmm,ew is longitude
|
|
||||||
* wname is the waypoint name
|
|
||||||
* *99 is checksum
|
|
||||||
*/
|
|
||||||
|
|
||||||
snprintf (sentence, sizeof(sentence), "$GPWPL,%s,%s,%s,%s,%s", slat, slat_ns, slong, slong_ew, wname);
|
|
||||||
append_checksum (sentence);
|
|
||||||
nmea_send_sentence (sentence);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Garmin - https://www8.garmin.com/support/pdf/NMEA_0183.pdf
|
|
||||||
* http://gpsinformation.net/mag-proto.htm
|
|
||||||
*
|
|
||||||
* $PGRMW,wname,alt,symbol,comment*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
*
|
|
||||||
* wname is waypoint name. Must match existing waypoint.
|
|
||||||
* alt is altitude in meters.
|
|
||||||
* symbol is symbol code. Hexadecimal up to FFFF.
|
|
||||||
* See Garmin Device Interface Specification 001-0063-00.
|
|
||||||
* comment is comment for the waypoint.
|
|
||||||
* *99 is checksum
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (alt == G_UNKNOWN) {
|
|
||||||
strcpy (salt, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf (salt, sizeof(salt), "%.1f", alt);
|
|
||||||
}
|
|
||||||
grm_sym = 0x1234; // TODO
|
|
||||||
|
|
||||||
snprintf (sentence, sizeof(sentence), "$PGRMW,%s,%s,%04X,%s", wname, salt, grm_sym, comment);
|
|
||||||
append_checksum (sentence);
|
|
||||||
nmea_send_sentence (sentence);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Magellan - http://www.gpsinformation.org/mag-proto-2-11.pdf
|
|
||||||
*
|
|
||||||
* $PMGNWPL,ddmm.mmmm,ns,dddmm.mmmm,ew,alt,unit,wname,comment,icon,xx*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
* ddmm.mmmm,ns is latitude
|
|
||||||
* dddmm.mmmm,ew is longitude
|
|
||||||
* alt is altitude
|
|
||||||
* unit is M for meters or F for feet
|
|
||||||
* wname is the waypoint name
|
|
||||||
* comment is message or comment
|
|
||||||
* icon is one or two letters for icon code
|
|
||||||
* xx is waypoint type which is optional, not well
|
|
||||||
* defined, and not used in their example.
|
|
||||||
* *99 is checksum
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: icon
|
|
||||||
|
|
||||||
snprintf (sicon, sizeof(sicon), "??");
|
|
||||||
snprintf (sentence, sizeof(sentence), "$PMGNWPL,%s,%s,%s,%s,%s,M,%s,%s,%s",
|
|
||||||
slat, slat_ns, slong, slong_ew, salt, wname, comment, sicon);
|
|
||||||
append_checksum (sentence);
|
|
||||||
nmea_send_sentence (sentence);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Kenwood - Speculation due to no official spec found so far.
|
|
||||||
*
|
|
||||||
* $PKWDWPL,hhmmss,v,ddmm.mmmm,ns,dddmm.mmmm,ew,speed,course,ddmmyy,alt,wname,ts*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
* hhmmss is time in UTC. Should we supply current
|
|
||||||
* time or only pass along time from
|
|
||||||
* received signal?
|
|
||||||
* v indicates valid data ?????????????????
|
|
||||||
* Why would we send if not valid?
|
|
||||||
* ddmm.mmmm,ns is latitude
|
|
||||||
* dddmm.mmmm,ew is longitude
|
|
||||||
* speed is speed in UNITS ??? knots ?????
|
|
||||||
* course is course in degrees
|
|
||||||
* ddmmyy is date. Same question as time.
|
|
||||||
* alt is altitude. in UNITS ??? meters ???
|
|
||||||
* wname is the waypoint name
|
|
||||||
* ts are the table and symbol.
|
|
||||||
* Non-standard parsing would be required
|
|
||||||
* to deal with these for symbol:
|
|
||||||
* , Boy Scouts / Girl Scouts
|
|
||||||
* * SnowMobile / Snow
|
|
||||||
* *99 is checksum
|
|
||||||
*
|
|
||||||
* Oddly, there is not place for comment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (speed == G_UNKNOWN) {
|
|
||||||
strcpy (sspeed, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf (sspeed, sizeof(sspeed), "%.1f", speed);
|
|
||||||
}
|
|
||||||
if (course == G_UNKNOWN) {
|
|
||||||
strcpy (scourse, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf (scourse, sizeof(scourse), "%.1f", course);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: how to handle time & date ???
|
|
||||||
|
|
||||||
strcpy (stime, "123456");
|
|
||||||
strcpy (sdate, "123456");
|
|
||||||
|
|
||||||
snprintf (sentence, sizeof(sentence), "$PKWDWPL,%s,V,%s,%s,%s,%s,%s,%s,%s,%s,%s,%c%c",
|
|
||||||
stime, slat, slat_ns, slong, slong_ew,
|
|
||||||
sspeed, scourse, sdate, salt, wname, symtab, symbol);
|
|
||||||
append_checksum (sentence);
|
|
||||||
nmea_send_sentence (sentence);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One application recognizes these. Not implemented at this time.
|
|
||||||
*
|
|
||||||
* $GPTLL,01,ddmm.mmmm,ns,dddmm.mmmm,ew,tname,000000.00,T,R*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
* ddmm.mmmm,ns is latitude
|
|
||||||
* dddmm.mmmm,ew is longitude
|
|
||||||
* tname is the target name
|
|
||||||
* 000000.00 is timestamp ???
|
|
||||||
* T is target status (S for need help)
|
|
||||||
* R is reference target ???
|
|
||||||
* *99 is checksum
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* $GPTXT,01,01,tname,message*99
|
|
||||||
*
|
|
||||||
* Where,
|
|
||||||
*
|
|
||||||
* 01 is total number of messages in transmission
|
|
||||||
* 01 is message number in this transmission
|
|
||||||
* tname is target name. Should match name in WPL or TTL.
|
|
||||||
* message is the message.
|
|
||||||
* *99 is checksum
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
} /* end nmea_send_waypoint */
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
* d710a menu 603 $GPWPL $PMGNWPL $PKWDWPL
|
|
||||||
|
|
||||||
symbol mapping
|
|
||||||
|
|
||||||
https://freepository.com:444/50lItuLQ7fW6s-web/browser/Tracker2/trunk/sources/waypoint.c?rev=108
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Data Transmission Protocol For Magellan Products - version 2.11
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$PMGNWPL,4651.529,N,07111.425,W,0000000,M,GC5A5F, GC. The straight line,a*13
|
|
||||||
$PMGNWPL,3549.499,N,08650.827,W,0000257,M,HOME,HOME,c*4D
|
|
||||||
|
|
||||||
http://gpsbabel.sourcearchive.com/documentation/1.3.7~cvs1/magproto_8c-source.html
|
|
||||||
|
|
||||||
sscanf(trkmsg,"$PMGNWPL,%lf,%c,%lf,%c,%d,%c,%[^,],%[^,]",
|
|
||||||
&latdeg,&latdir,
|
|
||||||
&lngdeg,&lngdir,
|
|
||||||
&alt,&altunits,shortname,descr); then icon
|
|
||||||
|
|
||||||
snprintf(obuf, sizeof(), "PMGNWPL,%4.3f,%c,%09.3f,%c,%07.0f,M,%-.*s,%-.46s,%s",
|
|
||||||
lat, ilat < 0 ? 'S' : 'N',
|
|
||||||
lon, ilon < 0 ? 'W' : 'E',
|
|
||||||
waypointp->altitude == unknown_alt ?
|
|
||||||
0 : waypointp->altitude,
|
|
||||||
wpt_len,
|
|
||||||
owpt,
|
|
||||||
odesc,
|
|
||||||
icon_token);
|
|
||||||
|
|
||||||
https://freepository.com:444/50lItuLQ7fW6s-web/changeset/108/Tracker2/trunk/sources/waypoint.c
|
|
||||||
|
|
||||||
$PMGNWPL,4106.003,S,14640.214,E,0000069,M,KISSING SPOT,,a*3C
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
https://freepository.com:444/50lItuLQ7fW6s-web/changeset/325
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void nmea_send_sentence (char *sent)
|
|
||||||
{
|
|
||||||
|
|
||||||
int err;
|
|
||||||
int len = strlen(sent);
|
|
||||||
|
|
||||||
|
|
||||||
if (nmea_port_fd == MYFDERROR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
text_color_set(DW_COLOR_XMIT);
|
|
||||||
dw_printf ("%s\n", sent);
|
|
||||||
|
|
||||||
if (nmea_debug) {
|
|
||||||
// TODO: debugg out... nmea_debug_print (TO_CLIENT, NULL, nmea_buff+1, nmea_len-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: need to append CR LF.
|
|
||||||
|
|
||||||
serial_port_write (nmea_port_fd, sent, len);
|
|
||||||
|
|
||||||
} /* nmea_send_sentence */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* end nmea.c */
|
|
19
nmea.h
19
nmea.h
|
@ -1,19 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Name: nmea.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ax25_pad.h" /* for packet_t */
|
|
||||||
|
|
||||||
#include "config.h" /* for struct misc_config_s */
|
|
||||||
|
|
||||||
|
|
||||||
void nmea_init (struct misc_config_s *misc_config);
|
|
||||||
|
|
||||||
void nmea_set_debug (int n);
|
|
||||||
|
|
||||||
void nmea_send_waypoint (char *wname_in, double dlat, double dlong, char symtab, char symbol,
|
|
||||||
float alt, float course, float speed, char *comment);
|
|
||||||
|
|
||||||
/* end nmea.h */
|
|
|
@ -1,6 +1,9 @@
|
||||||
/* serial_port.h */
|
/* serial_port.h */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SERIAL_PORT_H
|
||||||
|
#define SERIAL_PORT_H 1
|
||||||
|
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
|
|
||||||
|
@ -25,3 +28,6 @@ extern int serial_port_write (MYFDTYPE fd, char *str, int len);
|
||||||
extern int serial_port_get1 (MYFDTYPE fd);
|
extern int serial_port_get1 (MYFDTYPE fd);
|
||||||
|
|
||||||
extern void serial_port_close (MYFDTYPE fd);
|
extern void serial_port_close (MYFDTYPE fd);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
/* Dire Wolf version 1.3 */
|
/* Dire Wolf version 1.4 */
|
||||||
|
|
||||||
#define APP_TOCALL "APDW"
|
#define APP_TOCALL "APDW"
|
||||||
|
|
||||||
#define MAJOR_VERSION 1
|
#define MAJOR_VERSION 1
|
||||||
#define MINOR_VERSION 3
|
#define MINOR_VERSION 4
|
||||||
//#define EXTRA_VERSION "Beta Test"
|
//#define EXTRA_VERSION "Beta Test"
|
||||||
|
|
|
@ -0,0 +1,624 @@
|
||||||
|
//
|
||||||
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, 2015, 2016 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
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//#define DEBUG 1
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Module: waypoint.c
|
||||||
|
*
|
||||||
|
* Purpose: Send NMEA waypoint sentences to GPS display or mapping application.
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if __WIN32__
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#define __USE_XOPEN2KXSI 1
|
||||||
|
#define __USE_XOPEN 1
|
||||||
|
//#define __USE_POSIX 1
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "direwolf.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "textcolor.h"
|
||||||
|
#include "latlong.h"
|
||||||
|
#include "waypoint.h"
|
||||||
|
#include "grm_sym.h" /* Garmin symbols */
|
||||||
|
#include "mgn_icon.h" /* Magellan icons */
|
||||||
|
#include "dwgpsnmea.h"
|
||||||
|
#include "serial_port.h"
|
||||||
|
|
||||||
|
|
||||||
|
static MYFDTYPE s_waypoint_port_fd = MYFDERROR;
|
||||||
|
|
||||||
|
static int s_waypoint_formats = 0; /* which formats should we generate? */
|
||||||
|
|
||||||
|
static int s_waypoint_debug = 0; /* Print information flowing to attached device. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void append_checksum (char *sentence);
|
||||||
|
static void send_sentence (char *sent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void waypoint_set_debug (int n)
|
||||||
|
{
|
||||||
|
s_waypoint_debug = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: waypoint_init
|
||||||
|
*
|
||||||
|
* Purpose: Initialization for waypoint output port.
|
||||||
|
*
|
||||||
|
* Inputs: mc - Pointer to configuration options.
|
||||||
|
*
|
||||||
|
* ->waypoint_port - Name of serial port. COM1, /dev/ttyS0, etc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* (currently none) - speed, baud. Default 4800 if not set
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ->waypoint_formats - Set of formats enabled.
|
||||||
|
* If none set, default to generic & Kenwood.
|
||||||
|
*
|
||||||
|
* Global output: s_waypoint_port_fd
|
||||||
|
*
|
||||||
|
* Description: First to see if this is shared with GPS input.
|
||||||
|
* If not, open serial port.
|
||||||
|
*
|
||||||
|
* Restriction: MUST be done after GPS init because we might be sharing the
|
||||||
|
* same serial port device.
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
void waypoint_init (struct misc_config_s *mc)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
text_color_set (DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("waypoint_init() device=%s formats=%d\n", mc->waypoint_port, mc->waypoint_formats);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
* Are we sharing with GPS input?
|
||||||
|
* First try to get fd if they have same device name.
|
||||||
|
* If that fails, do own serial port open.
|
||||||
|
*/
|
||||||
|
if (strlen(mc->waypoint_port) > 0) {
|
||||||
|
|
||||||
|
s_waypoint_port_fd = dwgpsnmea_get_fd (mc->waypoint_port, 4800);
|
||||||
|
|
||||||
|
if (s_waypoint_port_fd == MYFDERROR) {
|
||||||
|
s_waypoint_port_fd = serial_port_open (mc->waypoint_port, 4800);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text_color_set (DW_COLOR_INFO);
|
||||||
|
dw_printf ("Note: Sharing same port for GPS input and waypoint output.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_waypoint_port_fd == MYFDERROR) {
|
||||||
|
text_color_set (DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Unable to open %s for waypoint output.\n", mc->waypoint_port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_waypoint_formats = mc->waypoint_formats;
|
||||||
|
if (s_waypoint_formats == 0) {
|
||||||
|
s_waypoint_formats = WPT_FORMAT_NMEA_GENERIC | WPT_FORMAT_KENWOOD;
|
||||||
|
}
|
||||||
|
if (s_waypoint_formats & WPT_FORMAT_GARMIN) {
|
||||||
|
s_waypoint_formats |= WPT_FORMAT_NMEA_GENERIC; /* See explanation below. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
text_color_set (DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("end of waypoint_init: s_waypoint_port_fd = %d\n", s_waypoint_port_fd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: append_checksum
|
||||||
|
*
|
||||||
|
* Purpose: Append checksum to the sentence.
|
||||||
|
*
|
||||||
|
* In/out: sentence - NMEA sentence beginning with '$'.
|
||||||
|
*
|
||||||
|
* Description: Checksum is exclusive of characters except leading '$'.
|
||||||
|
* We append '*' and an upper case two hexadecimal value.
|
||||||
|
*
|
||||||
|
* Don't add CR/LF at this point.
|
||||||
|
*
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void append_checksum (char *sentence)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int cs;
|
||||||
|
|
||||||
|
assert (sentence[0] == '$');
|
||||||
|
|
||||||
|
cs = 0;
|
||||||
|
for (p = sentence+1; *p != '\0'; p++) {
|
||||||
|
cs ^= *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (p, "*%02X", cs & 0xff);
|
||||||
|
|
||||||
|
} /* end append_checksum */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: nema_send_waypoint
|
||||||
|
*
|
||||||
|
* Purpose: Convert APRS position or object into NMEA waypoint sentence
|
||||||
|
* for use by a GPS display or other mapping application.
|
||||||
|
*
|
||||||
|
* Inputs: wname_in - Name of waypoint. Max of 9 characters.
|
||||||
|
* dlat - Latitude.
|
||||||
|
* dlong - Longitude.
|
||||||
|
* symtab - Symbol table or overlay character.
|
||||||
|
* symbol - Symbol code.
|
||||||
|
* alt - Altitude in meters or G_UNKNOWN.
|
||||||
|
* course - Course in degrees or G_UNKNOWN for unknown.
|
||||||
|
* speed - Speed in knots or G_UNKNOWN.
|
||||||
|
* comment_in - Description or message.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Description: Currently we send multiple styles. Maybe someday there might
|
||||||
|
* be an option to send a selected subset.
|
||||||
|
*
|
||||||
|
* $GPWPL - NMEA generic with only location and name.
|
||||||
|
* $PGRMW - Garmin, adds altitude, symbol, and comment
|
||||||
|
* to previously named waypoint.
|
||||||
|
* $PMGNWPL - Magellan, more complete for stationary objects.
|
||||||
|
* $PKWDWPL - Kenwood with APRS style symbol but missing comment.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* AvMap G5 notes:
|
||||||
|
*
|
||||||
|
* https://sites.google.com/site/kd7kuj/home/files?pli=1
|
||||||
|
* https://sites.google.com/site/kd7kuj/home/files/AvMapMessaging040810.pdf?attredirects=0&d=1
|
||||||
|
*
|
||||||
|
* It sends $GPGGA & $GPRMC with location.
|
||||||
|
* It understands generic $GPWPL and Kenwood $PKWDWPL.
|
||||||
|
*
|
||||||
|
* There are some proprietary $PAVP* used only for messaging.
|
||||||
|
* Messaging would be a separate project.
|
||||||
|
*
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
void waypoint_send_sentence (char *name_in, double dlat, double dlong, char symtab, char symbol,
|
||||||
|
float alt, float course, float speed, char *comment_in)
|
||||||
|
{
|
||||||
|
char wname[12]; /* Waypoint name. Any , or * removed. */
|
||||||
|
char slat[12]; /* DDMM.mmmm */
|
||||||
|
char slat_ns[2]; /* N or S */
|
||||||
|
char slong[12]; /* DDDMM.mmmm */
|
||||||
|
char slong_ew[2]; /* E or W */
|
||||||
|
char wcomment[256]; /* Comment. Any , or * removed. */
|
||||||
|
char salt[12]; /* altitude as string, empty if unknown */
|
||||||
|
char sspeed[12]; /* speed as string, empty if unknown */
|
||||||
|
char scourse[12]; /* course as string, empty if unknown */
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
char sentence[500];
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
text_color_set (DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("waypoint_send_sentence (\"%s\", \"%c%c\")\n", name_in, symtab, symbol);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to remove any , or * from name, symbol, or comment because they are field delimiters.
|
||||||
|
* Follow precedent of Geosat AvMap $PAVPMSG sentence and make the following substitutions:
|
||||||
|
*
|
||||||
|
* , -> |
|
||||||
|
* * -> ~
|
||||||
|
*
|
||||||
|
* The system on the other end would need to change them back after extracting the
|
||||||
|
* fields delimited by , or *.
|
||||||
|
* We will deal with the symbol in the Kenwood section.
|
||||||
|
* Needs to be left intact for other icon/symbol conversions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
strlcpy (wname, name_in, sizeof(wname));
|
||||||
|
for (p=wname; *p != '\0'; p++) {
|
||||||
|
if (*p == ',') *p = '|';
|
||||||
|
if (*p == '*') *p = '~';
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy (wcomment, comment_in, sizeof(wcomment));
|
||||||
|
for (p=wcomment; *p != '\0'; p++) {
|
||||||
|
if (*p == ',') *p = '|';
|
||||||
|
if (*p == '*') *p = '~';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert numeric values to character form.
|
||||||
|
* G_UNKNOWN value will result in an empty string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
latitude_to_nmea (dlat, slat, slat_ns);
|
||||||
|
longitude_to_nmea (dlong, slong, slong_ew);
|
||||||
|
|
||||||
|
|
||||||
|
if (alt == G_UNKNOWN) {
|
||||||
|
strcpy (salt, "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf (salt, sizeof(salt), "%.1f", alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speed == G_UNKNOWN) {
|
||||||
|
strcpy (sspeed, "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf (sspeed, sizeof(sspeed), "%.1f", speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (course == G_UNKNOWN) {
|
||||||
|
strcpy (scourse, "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf (scourse, sizeof(scourse), "%.1f", course);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NMEA Generic.
|
||||||
|
*
|
||||||
|
* Has only location and name. Rather disappointing.
|
||||||
|
*
|
||||||
|
* $GPWPL,ddmm.mmmm,ns,dddmm.mmmm,ew,wname*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
* ddmm.mmmm,ns is latitude
|
||||||
|
* dddmm.mmmm,ew is longitude
|
||||||
|
* wname is the waypoint name
|
||||||
|
* *99 is checksum
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s_waypoint_formats & WPT_FORMAT_NMEA_GENERIC) {
|
||||||
|
|
||||||
|
snprintf (sentence, sizeof(sentence), "$GPWPL,%s,%s,%s,%s,%s", slat, slat_ns, slong, slong_ew, wname);
|
||||||
|
append_checksum (sentence);
|
||||||
|
send_sentence (sentence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Garmin
|
||||||
|
*
|
||||||
|
* https://www8.garmin.com/support/pdf/NMEA_0183.pdf
|
||||||
|
*
|
||||||
|
* No location! Adds altitude, symbol, and comment to existing waypoint.
|
||||||
|
* So, we should always send the NMEA generic waypoint before this one.
|
||||||
|
* The init function should take care of that.
|
||||||
|
*
|
||||||
|
* $PGRMW,wname,alt,symbol,comment*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
*
|
||||||
|
* wname is waypoint name. Must match existing waypoint.
|
||||||
|
* alt is altitude in meters.
|
||||||
|
* symbol is symbol code. Hexadecimal up to FFFF.
|
||||||
|
* See Garmin Device Interface Specification
|
||||||
|
* 001-0063-00 for values of "symbol_type."
|
||||||
|
* comment is comment for the waypoint.
|
||||||
|
* *99 is checksum
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s_waypoint_formats & WPT_FORMAT_GARMIN) {
|
||||||
|
|
||||||
|
int i = symbol - ' ';
|
||||||
|
int grm_sym; /* Garmin symbol code. */
|
||||||
|
|
||||||
|
if (i >= 0 && i < SYMTAB_SIZE) {
|
||||||
|
if (symtab == '/') {
|
||||||
|
grm_sym = grm_primary_symtab[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grm_sym = grm_alternate_symtab[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grm_sym = sym_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (sentence, sizeof(sentence), "$PGRMW,%s,%s,%04X,%s", wname, salt, grm_sym, wcomment);
|
||||||
|
append_checksum (sentence);
|
||||||
|
send_sentence (sentence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Magellan
|
||||||
|
*
|
||||||
|
* http://www.gpsinformation.org/mag-proto-2-11.pdf Rev 2.11, Mar 2003, P/N 21-00091-000
|
||||||
|
* http://gpsinformation.net/mag-proto.htm Rev 1.0, Aug 1999, P/N 21-00091-000
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* $PMGNWPL,ddmm.mmmm,ns,dddmm.mmmm,ew,alt,unit,wname,comment,icon,xx*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
* ddmm.mmmm,ns is latitude
|
||||||
|
* dddmm.mmmm,ew is longitude
|
||||||
|
* alt is altitude
|
||||||
|
* unit is M for meters or F for feet
|
||||||
|
* wname is the waypoint name
|
||||||
|
* comment is message or comment
|
||||||
|
* icon is one or two letters for icon code
|
||||||
|
* xx is waypoint type which is optional, not well
|
||||||
|
* defined, and not used in their example
|
||||||
|
* so we won't use it.
|
||||||
|
* *99 is checksum
|
||||||
|
*
|
||||||
|
* Possible enhancement: If the "object report" has the kill option set, use $PMGNDWP
|
||||||
|
* to delete that specific waypoint.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s_waypoint_formats & WPT_FORMAT_MAGELLAN) {
|
||||||
|
|
||||||
|
int i = symbol - ' ';
|
||||||
|
char sicon[3]; /* Magellan icon string. Currently 1 or 2 characters. */
|
||||||
|
|
||||||
|
if (i >= 0 && i < SYMTAB_SIZE) {
|
||||||
|
if (symtab == '/') {
|
||||||
|
strlcpy (sicon, mgn_primary_symtab[i], sizeof(sicon));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strlcpy (sicon, mgn_alternate_symtab[i], sizeof(sicon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strlcpy (sicon, MGN_default, sizeof(sicon));
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (sentence, sizeof(sentence), "$PMGNWPL,%s,%s,%s,%s,%s,M,%s,%s,%s",
|
||||||
|
slat, slat_ns, slong, slong_ew, salt, wname, wcomment, sicon);
|
||||||
|
append_checksum (sentence);
|
||||||
|
send_sentence (sentence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kenwood
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* $PKWDWPL,hhmmss,v,ddmm.mm,ns,dddmm.mm,ew,speed,course,ddmmyy,alt,wname,ts*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
* hhmmss is time in UTC from the clock in the transceiver.
|
||||||
|
*
|
||||||
|
* This will be bogus if the clock was not set properly.
|
||||||
|
* It does not use the timestamp from a position
|
||||||
|
* report which could be useful.
|
||||||
|
*
|
||||||
|
* GPS Status A = active, V = void.
|
||||||
|
* It looks like this might be modeled after the GPS status values
|
||||||
|
* we see in $GPRMC. i.e. Does the transceiver know its location?
|
||||||
|
* I don’t see how that information would be relevant in this context.
|
||||||
|
* I've observed this under various conditions (No GPS, GPS with/without
|
||||||
|
* fix) and it has always been "V."
|
||||||
|
* (There is some information out there indicating this field
|
||||||
|
* can contain "I" for invalid but I don't think that is accurate.)
|
||||||
|
*
|
||||||
|
* ddmm.mm,ns is latitude. N or S.
|
||||||
|
* dddmm.mm,ew is longitude. E or W.
|
||||||
|
*
|
||||||
|
* The D710 produces two fractional digits for minutes.
|
||||||
|
* This is the same resolution most often used
|
||||||
|
* in APRS packets. Any additional resolution offered by
|
||||||
|
* the compressed format or the DAO option is not conveyed here.
|
||||||
|
* We will provide greater resolution.
|
||||||
|
*
|
||||||
|
* speed is speed over ground, knots.
|
||||||
|
* course is course over ground, degrees.
|
||||||
|
*
|
||||||
|
* Empty if not available.
|
||||||
|
*
|
||||||
|
* ddmmyy is date. See comments for time.
|
||||||
|
*
|
||||||
|
* alt is altitude, meters above mean sea level.
|
||||||
|
*
|
||||||
|
* Empty if no altitude is available.
|
||||||
|
*
|
||||||
|
* wname is the waypoint name. For an Object Report, the id is the object name.
|
||||||
|
* For a position report, it is the call of the sending station.
|
||||||
|
*
|
||||||
|
* An Object name can contain any printable characters.
|
||||||
|
* What if object name contains , or * characters?
|
||||||
|
* Those are field delimiter characters and it would be unfortunate
|
||||||
|
* if they appeared in a NMEA sentence data field.
|
||||||
|
*
|
||||||
|
* If there is a comma in the name, such as "test,5" the D710A displays
|
||||||
|
* it fine but we end up with an extra field.
|
||||||
|
*
|
||||||
|
* $PKWDWPL,150803,V,4237.14,N,07120.83,W,,,190316,,test,5,/'*30
|
||||||
|
*
|
||||||
|
* If the name contains an asterisk, it doesn't show up on the
|
||||||
|
* display and no waypoint sentence is generated.
|
||||||
|
* We will substitute these two characters following the AvMap precedent.
|
||||||
|
*
|
||||||
|
* $PKWDWPL,204714,V,4237.1400,N,07120.8300,W,,,200316,,test|5,/'*61
|
||||||
|
* $PKWDWPL,204719,V,4237.1400,N,07120.8300,W,,,200316,,test~6,/'*6D
|
||||||
|
*
|
||||||
|
* ts are the table and symbol.
|
||||||
|
*
|
||||||
|
* What happens if the symbol is comma or asterisk?
|
||||||
|
* , Boy Scouts / Girl Scouts
|
||||||
|
* * SnowMobile / Snow
|
||||||
|
*
|
||||||
|
* the D710A just pushes them thru without checking.
|
||||||
|
* These would not be parsed properly:
|
||||||
|
*
|
||||||
|
* $PKWDWPL,150753,V,4237.14,N,07120.83,W,,,190316,,test3,/,*1B
|
||||||
|
* $PKWDWPL,150758,V,4237.14,N,07120.83,W,,,190316,,test4,/**3B
|
||||||
|
*
|
||||||
|
* We perform the usual substitution and the other end would
|
||||||
|
* need to change them back after extracting from NMEA sentence.
|
||||||
|
*
|
||||||
|
* $PKWDWPL,204704,V,4237.1400,N,07120.8300,W,,,200316,,test3,/|*41
|
||||||
|
* $PKWDWPL,204709,V,4237.1400,N,07120.8300,W,,,200316,,test4,/~*49
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* *99 is checksum
|
||||||
|
*
|
||||||
|
* Oddly, there is no place for comment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (s_waypoint_formats & WPT_FORMAT_KENWOOD) {
|
||||||
|
|
||||||
|
time_t now;
|
||||||
|
struct tm tm;
|
||||||
|
char stime[8];
|
||||||
|
char sdate[8];
|
||||||
|
char ken_sym; /* APRS symbol with , or * substituted. */
|
||||||
|
|
||||||
|
now = time(NULL);
|
||||||
|
gmtime_r (&now, &tm);
|
||||||
|
strftime (stime, sizeof(stime), "%H%M%S", &tm);
|
||||||
|
strftime (sdate, sizeof(sdate), "%d%m%y", &tm);
|
||||||
|
|
||||||
|
// A symbol code of , or * would not be good because
|
||||||
|
// they are field delimiters for NMEA sentences.
|
||||||
|
|
||||||
|
// The AvMap G5 to Kenwood protocol description performs a substitution
|
||||||
|
// for these characters that appear in message text.
|
||||||
|
// , -> |
|
||||||
|
// * -> ~
|
||||||
|
|
||||||
|
// Those two are listed as "TNC Stream Switch" and are not used for symbols.
|
||||||
|
// It might be reasonable assumption that this same substitution might be
|
||||||
|
// used for the symbol code.
|
||||||
|
|
||||||
|
if (symbol == ',') ken_sym = '|';
|
||||||
|
else if (symbol == '*') ken_sym = '~';
|
||||||
|
else ken_sym = symbol;
|
||||||
|
|
||||||
|
snprintf (sentence, sizeof(sentence), "$PKWDWPL,%s,V,%s,%s,%s,%s,%s,%s,%s,%s,%s,%c%c",
|
||||||
|
stime, slat, slat_ns, slong, slong_ew,
|
||||||
|
sspeed, scourse, sdate, salt, wname, symtab, ken_sym);
|
||||||
|
append_checksum (sentence);
|
||||||
|
send_sentence (sentence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One application recognizes these. Not implemented at this time.
|
||||||
|
*
|
||||||
|
* $GPTLL,01,ddmm.mmmm,ns,dddmm.mmmm,ew,tname,000000.00,T,R*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
* ddmm.mmmm,ns is latitude
|
||||||
|
* dddmm.mmmm,ew is longitude
|
||||||
|
* tname is the target name
|
||||||
|
* 000000.00 is timestamp ???
|
||||||
|
* T is target status (S for need help)
|
||||||
|
* R is reference target ???
|
||||||
|
* *99 is checksum
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* $GPTXT,01,01,tname,message*99
|
||||||
|
*
|
||||||
|
* Where,
|
||||||
|
*
|
||||||
|
* 01 is total number of messages in transmission
|
||||||
|
* 01 is message number in this transmission
|
||||||
|
* tname is target name. Should match name in WPL or TTL.
|
||||||
|
* message is the message.
|
||||||
|
* *99 is checksum
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
} /* end waypoint_send_sentence */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append CR LF and send it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void send_sentence (char *sent)
|
||||||
|
{
|
||||||
|
|
||||||
|
char final[256];
|
||||||
|
|
||||||
|
|
||||||
|
if (s_waypoint_port_fd == MYFDERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_waypoint_debug) {
|
||||||
|
text_color_set(DW_COLOR_XMIT);
|
||||||
|
dw_printf ("%s\n", sent);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy (final, sent, sizeof(final));
|
||||||
|
strlcat (final, "\r\n", sizeof(final));
|
||||||
|
|
||||||
|
serial_port_write (s_waypoint_port_fd, final, strlen(final));
|
||||||
|
|
||||||
|
} /* send_sentence */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void waypoint_term ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (s_waypoint_port_fd != MYFDERROR) {
|
||||||
|
//serial_port_close (s_waypoint_port_fd);
|
||||||
|
s_waypoint_port_fd = MYFDERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end waypoint.c */
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Name: waypoint.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ax25_pad.h" /* for packet_t */
|
||||||
|
|
||||||
|
#include "config.h" /* for struct misc_config_s */
|
||||||
|
|
||||||
|
|
||||||
|
void waypoint_init (struct misc_config_s *misc_config);
|
||||||
|
|
||||||
|
void waypoint_set_debug (int n);
|
||||||
|
|
||||||
|
void waypoint_send_sentence (char *wname_in, double dlat, double dlong, char symtab, char symbol,
|
||||||
|
float alt, float course, float speed, char *comment_in);
|
||||||
|
|
||||||
|
void waypoint_term ();
|
||||||
|
|
||||||
|
|
||||||
|
/* end waypoint.h */
|
Loading…
Reference in New Issue