summaryrefslogtreecommitdiff
path: root/libloragw/inc/loragw_gps.h
blob: 94d1d2a2f0a39c0e6d19abb491b97f866e1cbd9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
  (C)2013 Semtech-Cycleo

Description:
    Library of functions to manage a GNSS module (typically GPS) for accurate
    timestamping of packets and synchronisation of gateways.
    A limited set of module brands/models are supported.

License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Michael Coracin
*/


#ifndef _LORAGW_GPS_H
#define _LORAGW_GPS_H

/* -------------------------------------------------------------------------- */
/* --- DEPENDANCIES --------------------------------------------------------- */

#define _GNU_SOURCE
#include <stdint.h>     /* C99 types */
#include <time.h>       /* time library */
#include <termios.h>    /* speed_t */
#include <unistd.h>     /* ssize_t */
#include <gpsd.h>
#include <gpsdclient.h>
#include <errno.h>      /* error messages */

#include "config.h"     /* library configuration options (dynamically generated) */
/* -------------------------------------------------------------------------- */
/* --- PUBLIC TYPES --------------------------------------------------------- */

/**
@struct coord_s
@brief Time solution required for timestamp to absolute time conversion
*/
struct tref {
    time_t          systime;    /*!> system time when solution was calculated */
    uint32_t        count_us;   /*!> reference concentrator internal timestamp */
    struct timespec utc;        /*!> reference UTC time (from GPS/NMEA) */
    struct timespec gps;        /*!> reference GPS time (since 01.Jan.1980) */
    double          xtal_err;   /*!> raw clock error (eg. <1 'slow' XTAL) */
};

/**
@struct coord_s
@brief Geodesic coordinates
*/
struct coord_s {
    double  lat;    /*!> latitude [-90,90] (North +, South -) */
    double  lon;    /*!> longitude [-180,180] (East +, West -)*/
    short   alt;    /*!> altitude in meters (WGS 84 geoid ref.) */
};

/**
@enum gps_msg
@brief Type of GPS (and other GNSS) sentences
*/
enum gps_msg {
    UNKNOWN,         /*!> neutral value */
    IGNORED,         /*!> frame was not parsed by the system */
    INVALID,         /*!> system try to parse frame but failed */
    INCOMPLETE,      /*!> frame parsed was missing bytes */
    /* NMEA messages of interest */
    NMEA_RMC,        /*!> Recommended Minimum data (time + date) */
    NMEA_GGA,        /*!> Global positioning system fix data (pos + alt) */
    NMEA_GNS,        /*!> GNSS fix data (pos + alt, sat number) */
    NMEA_ZDA,        /*!> Time and Date */
    /* NMEA message useful for time reference quality assessment */
    NMEA_GBS,        /*!> GNSS Satellite Fault Detection */
    NMEA_GST,        /*!> GNSS Pseudo Range Error Statistics */
    NMEA_GSA,        /*!> GNSS DOP and Active Satellites (sat number) */
    NMEA_GSV,        /*!> GNSS Satellites in View (sat SNR) */
    /* Misc. NMEA messages */
    NMEA_GLL,        /*!> Latitude and longitude, with time fix and status */
    NMEA_TXT,        /*!> Text Transmission */
    NMEA_VTG,        /*!> Course over ground and Ground speed */
    /* uBlox proprietary NMEA messages of interest */
    UBX_NAV_TIMEGPS, /*!> GPS Time Solution */
    UBX_NAV_TIMEUTC  /*!> UTC Time Solution */
};

// struct gps_data_t gpsdata;
/* -------------------------------------------------------------------------- */
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */

#define LGW_GPS_SUCCESS 0
#define LGW_GPS_ERROR   -1

#define LGW_GPS_MIN_MSG_SIZE      (8)
#define LGW_GPS_UBX_SYNC_CHAR     (0xB5)
#define LGW_GPS_NMEA_SYNC_CHAR    (0x24)

/* -------------------------------------------------------------------------- */
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */

/**
@brief Configure a GPS module

@param gpsdata handler for gpsd data
@param source source for setup of gpsd
@return success if the function was able to connect and configure a GPSD stream
*/
int lgw_gps_enable(struct gps_data_t *gpsdata, struct fixsource_t *source);

/**
@brief Restore GPS serial configuration and close serial device

@param gpsdata handler for gpsd data
@return success if the function was able to complete
*/
int lgw_gps_disable(struct gps_data_t *gpsdata);

/**
@brief Parse messages coming from the GPS system (or other GNSS)

@param serial_buff pointer to the string to be parsed
@param buff_size maximum string lengths for NMEA parsing (incl. null char)
@return type of frame parsed

The RAW NMEA sentences are parsed to a global set of variables shared with the
lgw_gps_get function.
If the lgw_parse_nmea and lgw_gps_get are used in different threads, a mutex
lock must be acquired before calling either function.
*/
enum gps_msg lgw_parse_nmea(const char* serial_buff, int buff_size);

/**
@brief Parse Ublox proprietary messages coming from the GPS system

@param serial_buff pointer to the string to be parsed
@param buff_size maximum string lengths for UBX parsing (incl. null char)
@param msg_size number of bytes parsed as UBX message if found
@return type of frame parsed

The RAW UBX sentences are parsed to a global set of variables shared with the
lgw_gps_get function.
If the lgw_parse_ubx and lgw_gps_get are used in different threads, a mutex
lock must be acquired before calling either function.
*/
enum gps_msg lgw_parse_ubx(const char* serial_buff, size_t buff_size, size_t *msg_size);

/**
@brief Get the GPS solution (space & time) for the concentrator

@param utc pointer to store UTC time, with ns precision (NULL to ignore)
@param gps_time pointer to store GPS time, with ns precision (NULL to ignore)
@param loc pointer to store coordinates (NULL to ignore)
@param err pointer to store coordinates standard deviation (NULL to ignore)
@return success if the chosen elements could be returned

This function read the global variables generated by the NMEA/UBX parsing
functions lgw_parse_nmea/lgw_parse_ubx. It returns time and location data in a
format that is exploitable by other functions in that library sub-module.
If the lgw_parse_nmea/lgw_parse_ubx and lgw_gps_get are used in different
threads, a mutex lock must be acquired before calling either function.
*/
int lgw_gps_get(struct timespec *utc, struct timespec *gps_time, struct coord_s *loc, struct coord_s *err);

/**
@brief Get time and position information from the serial GPS last message received
@param utc UTC time, with ns precision (leap seconds are ignored)
@param gps_time timestamp of last time pulse from the GPS module converted to the UNIX epoch
       (leap seconds are ignored)
@param loc location information
@param err location error estimate if supported
@return success if timestamp was read and time reference could be refreshed

Set systime to 0 in ref to trigger initial synchronization.
*/
int lgw_gps_sync(struct tref *ref, uint32_t count_us, struct timespec gps_time);

/**
@brief Convert concentrator timestamp counter value to UTC time

@param ref time reference structure required for time conversion
@param count_us internal timestamp counter of the LoRa concentrator
@param utc pointer to store UTC time, with ns precision (leap seconds ignored)
@return success if the function was able to convert timestamp to UTC

This function is typically used when a packet is received to transform the
internal counter-based timestamp in an absolute timestamp with an accuracy in
the order of a couple microseconds (ns resolution).
*/
int lgw_cnt2utc(struct tref ref, uint32_t count_us, struct timespec* utc);

/**
@brief Convert UTC time to concentrator timestamp counter value

@param ref time reference structure required for time conversion
@param utc UTC time, with ns precision (leap seconds are ignored)
@param count_us pointer to store internal timestamp counter of LoRa concentrator
@return success if the function was able to convert UTC to timestamp

This function is typically used when a packet must be sent at an accurate time
(eg. to send a piggy-back response after receiving a packet from a node) to
transform an absolute UTC time into a matching internal concentrator timestamp.
*/
int lgw_utc2cnt(struct tref ref,struct timespec utc, uint32_t* count_us);

/**
@brief Convert concentrator timestamp counter value to GPS time

@param ref time reference structure required for time conversion
@param count_us internal timestamp counter of the LoRa concentrator
@param gps_time pointer to store GPS time, with ns precision (leap seconds ignored)
@return success if the function was able to convert timestamp to GPS time

This function is typically used when a packet is received to transform the
internal counter-based timestamp in an absolute timestamp with an accuracy in
the order of a millisecond.
*/
int lgw_cnt2gps(struct tref ref, uint32_t count_us, struct timespec* gps_time);

/**
@brief Convert GPS time to concentrator timestamp counter value

@param ref time reference structure required for time conversion
@param gps_time GPS time, with ns precision (leap seconds are ignored)
@param count_us pointer to store internal timestamp counter of LoRa concentrator
@return success if the function was able to convert GPS time to timestamp

This function is typically used when a packet must be sent at an accurate time
(eg. to send a piggy-back response after receiving a packet from a node) to
transform an absolute GPS time into a matching internal concentrator timestamp.
*/
int lgw_gps2cnt(struct tref ref, struct timespec gps_time, uint32_t* count_us);

#endif

/* --- EOF ------------------------------------------------------------------ */