// // This file is part of Dire Wolf, an amateur radio packet TNC. // // Copyright (C) 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 . // /*------------------------------------------------------------------ * * Module: dwgps.c * * Purpose: Interface for obtaining location from GPS. * * Description: This is a wrapper for two different implementations: * * (1) Read NMEA sentences from a serial port (or USB * that looks line one). Available for all platforms. * * (2) Read from gpsd. Not available for Windows. * Including this is optional because it depends * on another external software component. * * * API: dwgps_init Connect to data stream at start up time. * * dwgps_read Return most recent location to application. * * dwgps_print Print contents of structure for debugging. * * dwgps_term Shutdown on exit. * * * from below: dwgps_set_data Called from other two implementations to * save data until it is needed. * *---------------------------------------------------------------*/ #include "direwolf.h" #include #include #include #include #include #include "textcolor.h" #include "dwgps.h" #include "dwgpsnmea.h" #include "dwgpsd.h" static int s_dwgps_debug = 0; /* Enable debug output. */ /* >= 2 show updates from GPS. */ /* >= 1 show results from dwgps_read. */ /* * The GPS reader threads deposit current data here when it becomes available. * dwgps_read returns it to the requesting application. * * A critical region to avoid inconsistency between fields. */ static dwgps_info_t s_dwgps_info = { .timestamp = 0, .fix = DWFIX_NOT_INIT, /* to detect read without init. */ .dlat = G_UNKNOWN, .dlon = G_UNKNOWN, .speed_knots = G_UNKNOWN, .track = G_UNKNOWN, .altitude = G_UNKNOWN }; static dw_mutex_t s_gps_mutex; /*------------------------------------------------------------------- * * Name: dwgps_init * * Purpose: Initialize the GPS interface. * * Inputs: pconfig Configuration settings. This might include * serial port name for direct connect and host * name or address for network connection. * * debug - If >= 1, print results when dwgps_read is called. * (In this file.) * * If >= 2, location updates are also printed. * (In other two related files.) * * Returns: none * * Description: Call corresponding functions for implementations. * Normally we would expect someone to use either GPSNMEA or * GPSD but there is nothing to prevent use of both at the * same time. * *--------------------------------------------------------------------*/ void dwgps_init (struct misc_config_s *pconfig, int debug) { s_dwgps_debug = debug; dw_mutex_init (&s_gps_mutex); dwgpsnmea_init (pconfig, debug); #if ENABLE_GPSD dwgpsd_init (pconfig, debug); #endif SLEEP_MS(500); /* So receive thread(s) can clear the */ /* not init status before it gets checked. */ } /* end dwgps_init */ /*------------------------------------------------------------------- * * Name: dwgps_clear * * Purpose: Clear the gps info structure. * *--------------------------------------------------------------------*/ void dwgps_clear (dwgps_info_t *gpsinfo) { gpsinfo->timestamp = 0; gpsinfo->fix = DWFIX_NOT_SEEN; gpsinfo->dlat = G_UNKNOWN; gpsinfo->dlon = G_UNKNOWN; gpsinfo->speed_knots = G_UNKNOWN; gpsinfo->track = G_UNKNOWN; gpsinfo->altitude = G_UNKNOWN; } /*------------------------------------------------------------------- * * Name: dwgps_read * * Purpose: Return most recent location data available. * * Outputs: gpsinfo - Structure with latitude, longitude, etc. * * Returns: Position fix quality. Same as in structure. * * *--------------------------------------------------------------------*/ dwfix_t dwgps_read (dwgps_info_t *gpsinfo) { dw_mutex_lock (&s_gps_mutex); memcpy (gpsinfo, &s_dwgps_info, sizeof(*gpsinfo)); dw_mutex_unlock (&s_gps_mutex); if (s_dwgps_debug >= 1) { text_color_set (DW_COLOR_DEBUG); dwgps_print ("gps_read: ", gpsinfo); } // TODO: Should we check timestamp and complain if very stale? // or should we leave that up to the caller? return (s_dwgps_info.fix); } /*------------------------------------------------------------------- * * Name: dwgps_print * * Purpose: Print gps information for debugging. * * Inputs: msg - Message for prefix on line. * gpsinfo - Structure with latitude, longitude, etc. * * Description: Caller is responsible for setting text color. * *--------------------------------------------------------------------*/ void dwgps_print (char *msg, dwgps_info_t *gpsinfo) { dw_printf ("%stime=%d fix=%d lat=%.6f lon=%.6f trk=%.0f spd=%.1f alt=%.0f\n", msg, (int)gpsinfo->timestamp, (int)gpsinfo->fix, gpsinfo->dlat, gpsinfo->dlon, gpsinfo->track, gpsinfo->speed_knots, gpsinfo->altitude); } /* end dwgps_set_data */ /*------------------------------------------------------------------- * * Name: dwgps_term * * Purpose: Shut down GPS interface before exiting from application. * * Inputs: none. * * Returns: none. * *--------------------------------------------------------------------*/ void dwgps_term (void) { dwgpsnmea_term (); #if ENABLE_GPSD dwgpsd_term (); #endif } /* end dwgps_term */ /*------------------------------------------------------------------- * * Name: dwgps_set_data * * Purpose: Called by the GPS interfaces when new data is available. * * Inputs: gpsinfo - Structure with latitude, longitude, etc. * *--------------------------------------------------------------------*/ void dwgps_set_data (dwgps_info_t *gpsinfo) { /* Debug print is handled by the two callers so */ /* we can distinguish the source. */ dw_mutex_lock (&s_gps_mutex); memcpy (&s_dwgps_info, gpsinfo, sizeof(s_dwgps_info)); dw_mutex_unlock (&s_gps_mutex); } /* end dwgps_set_data */ /* end dwgps.c */