mbgtools-lx  4.2.8
gpsutils.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: gpsutils.c 1.10 2017/07/05 13:57:06 martin REL_M $
5  *
6  * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
7  *
8  * Description:
9  * Utility functions useful with GPS data.
10  *
11  * -----------------------------------------------------------------------
12  * $Log: gpsutils.c $
13  * Revision 1.10 2017/07/05 13:57:06 martin
14  * Use save string functions from str_util.c.
15  * Quieted some compiler warninges.
16  * Added doxygen comments.
17  * Revision 1.9 2013/01/30 16:10:08 martin
18  * Exclude some code from compiling by default, and
19  * thus don't require pcpslstr.h by default.
20  * Revision 1.8 2012/10/15 14:27:05Z martin
21  * Exclude sprint_fixed_freq() from build except for Borland C / Windows.
22  * Revision 1.7 2010/07/15 09:32:09 martin
23  * Use DEG character definition from pcpslstr.h.
24  * Revision 1.6 2004/12/28 11:21:26Z martin
25  * Omit trap if fixed_freq is 0.
26  * Use C99 fixed-size data types were required.
27  * Revision 1.5 2003/02/04 09:20:04Z MARTIN
28  * New functions sprint_alt(), sprint_fixed_freq().
29  * Revision 1.4 2003/01/31 13:45:19 MARTIN
30  * sprint_pos_geo() returns N/A if position not valid.
31  * Revision 1.3 2002/12/12 16:07:04 martin
32  * New functions swap_pos_doubles(), sprint_dms(),
33  * and sprint_pos_geo().
34  * Revision 1.2 2001/02/05 09:39:12Z MARTIN
35  * New file header.
36  * Change include file name to lower case.
37  * Source code cleanup.
38  *
39  **************************************************************************/
40 
41 #define _GPSUTILS
42  #include <gpsutils.h>
43 #undef _GPSUTILS
44 
45 #if defined( USE_SPRINTF )
46  #error USE_SPRINTF was obsoleted by USE_SNPRINTF. Please update project settings.
47 #endif
48 
49 #if !defined( USE_SNPRINTF )
50  #define USE_SNPRINTF 0
51 #endif
52 
53 #if !defined( _USE_GPSUTILS_FULL )
54  #if defined( MBG_TGT_WIN32 ) && defined( __BORLANDC__ )
55  #define _USE_GPSUTILS_FULL 1
56  #else
57  #define _USE_GPSUTILS_FULL 0
58  #endif
59 #endif
60 
61 #if USE_SNPRINTF
62  #include <str_util.h>
63 
64  #define DEG "deg"
65 #endif
66 
67 #if _USE_GPSUTILS_FULL
68  #include <str_util.h>
69  #include <math.h>
70 #endif
71 
72 #include <stdio.h>
73 #include <string.h>
74 
75 
76 #if USE_SNPRINTF || _USE_GPSUTILS_FULL
77 
78 static const char str_na[] = "N/A";
79 
80 #endif
81 
82 
83 
84 /*HDR*/
101 void swap_double( double *p )
102 {
103  uint16_t *wp1;
104  uint16_t *wp2;
105  uint16_t w;
106  int i;
107 
108  wp1 = (uint16_t *) p;
109  wp2 = ( (uint16_t *) p ) + 3;
110 
111  for ( i = 0; i < 2; i++ )
112  {
113  w = *wp1;
114  *wp1 = *wp2;
115  *wp2 = w;
116  wp1++;
117  wp2--;
118  }
119 
120 } // swap_double
121 
122 
123 
124 /*HDR*/
139 {
140  swap_double( &p->sqrt_A );
141  swap_double( &p->e );
142  swap_double( &p->M0 );
143  swap_double( &p->omega );
144  swap_double( &p->i0 );
145  swap_double( &p->OMEGA0 );
146  swap_double( &p->OMEGADOT );
147 
148  swap_double( &p->deltan );
149  swap_double( &p->idot );
150 
151  swap_double( &p->crc );
152  swap_double( &p->crs );
153  swap_double( &p->cuc );
154  swap_double( &p->cus );
155  swap_double( &p->cic );
156  swap_double( &p->cis );
157 
158  swap_double( &p->af0 );
159  swap_double( &p->af1 );
160  swap_double( &p->af2 );
161 
162  swap_double( &p->tgd );
163 
164 } /* swap_eph_doubles */
165 
166 
167 
168 /*HDR*/
183 {
184  swap_double( &p->sqrt_A );
185  swap_double( &p->e );
186  swap_double( &p->deltai );
187  swap_double( &p->OMEGA0 );
188  swap_double( &p->OMEGADOT );
189  swap_double( &p->omega );
190  swap_double( &p->M0 );
191  swap_double( &p->af0 );
192  swap_double( &p->af1 );
193 
194 } /* swap_alm_doubles */
195 
196 
197 
198 /*HDR*/
213 {
214  swap_double( &p->A0 );
215  swap_double( &p->A1 );
216 
217 } /* swap_utc_doubles */
218 
219 
220 
221 /*HDR*/
236 {
237  swap_double( &p->alpha_0 );
238  swap_double( &p->alpha_1 );
239  swap_double( &p->alpha_2 );
240  swap_double( &p->alpha_3 );
241 
242  swap_double( &p->beta_0 );
243  swap_double( &p->beta_1 );
244  swap_double( &p->beta_2 );
245  swap_double( &p->beta_3 );
246 
247 } /* swap_iono_doubles */
248 
249 
250 
251 /*HDR*/
266 {
267  int i;
268 
269  for ( i = 0; i < N_XYZ; i++ )
270  swap_double( &p->xyz[i] );
271 
272  for ( i = 0; i < N_LLA; i++ )
273  swap_double( &p->lla[i] );
274 
275  swap_double( &p->longitude.sec );
276  swap_double( &p->latitude.sec );
277 
278 } /* swap_pos_doubles */
279 
280 
281 
282 #if USE_SNPRINTF
283 
284 /*HDR*/
300 size_t snprint_dms( char *s, size_t max_len, const DMS *p, int prec )
301 {
302  size_t n = snprintf_safe( s, max_len, "%c %i" DEG "%02i'%02.*f\"",
303  p->prefix, p->deg, p->min,
304  prec, p->sec );
305 
306  return n;
307 
308 } // snprint_dms
309 
310 
311 
312 /*HDR*/
326 size_t snprint_alt( char *s, size_t max_len, double alt )
327 {
328  size_t n = snprintf_safe( s, max_len, "%.0fm", alt );
329 
330  return n;
331 
332 } // snprint_alt
333 
334 
335 
336 /*HDR*/
352 size_t snprint_pos_geo( char *s, size_t max_len, const POS *p, char sep, int prec )
353 {
354  size_t n = 0;
355 
356  if ( p->lla[LON] && p->lla[LAT] && p->lla[ALT] )
357  {
358  n += snprint_dms( &s[n], max_len - n, &p->latitude, prec );
359  n += snprintf_safe( &s[n], max_len - n, "%c", sep );
360  n += snprint_dms( &s[n], max_len - n, &p->longitude, prec );
361  n += snprintf_safe( &s[n], max_len - n, "%c", sep );
362  n += snprint_alt( &s[n], max_len - n, p->lla[ALT] );
363  }
364  else
365  n = sn_cpy_str_safe( s, max_len, str_na );
366 
367  return n;
368 
369 } // snprint_pos_geo
370 
371 #endif // USE_SNPRINTF
372 
373 
374 
375 #if _USE_GPSUTILS_FULL
376 
377 /*HDR*/
391 size_t snprint_fixed_freq( char *s, size_t max_len, FIXED_FREQ_INFO *p_ff )
392 {
393  double freq;
394  int range;
395  ushort unit;
396  ushort format;
397  size_t n = 0;
398 
399  // Before re-calculating frequency, range is the base 10 exponent
400  // to the frequency value which is represented in kHz.
401  // After calculating range from real frequency, range is represented
402  // as follows:
403  // range display format divisor format index calculation
404  // -3 100mHz 1.000 [/1e-3] -3 % 3 = -3 + 3 = 0 % 3 = 0
405  // -2 100mHz 10.00 [/1e-3] -2 % 3 = -2 + 3 = 1 % 3 = 1
406  // -1 100mHz 100.0 [/1e-3] -1 % 3 = -1 + 3 = 2 % 3 = 2
407  // 0 1Hz 1.000 [/1e0] 0 % 3 = 0 + 3 = 3 % 3 = 0
408  // 1 10Hz 10.00 [/1e0] 1 % 3 = 1 + 3 = 1 % 3 = 1
409  // 2 100Hz 100.0 [/1e0] 2 % 3 = 2 + 3 = 2 % 3 = 2
410  // 3 1kHz 1.000 [/1e3] 3 % 3 = 0 + 3 = 3 % 3 = 0
411  // 4 10kHz 10.00 [/1e3] 4 % 3 = 1 + 3 = 4 % 3 = 1
412  // 5 100kHz 100.0 [/1e3] 5 % 3 = 2 + 3 = 5 % 3 = 2
413  // 6 1MHz 1.000 [/1e6] 6 % 3 = 0 + 3 = 3 % 3 = 0
414  // 7 10MHz 10.00 [/1e6] 7 % 3 = 1 + 3 = 4 % 3 = 1
415  // 8 100MHz 100.0 [/1e6] 8 % 3 = 2 + 3 = 5 % 3 = 2
416 
417  // format string for fp output
418  static const char *fmt_str[] =
419  {
420  "%4.3lf%s",
421  "%4.2lf%s",
422  "%4.1lf%s",
423  };
424 
425  // Unit index and divisor are calculated as follows:
426  // range unit index calculation divisor calculation
427  // -3 mHz ( int )( ( -3 + 3 ) / 3 ) = 0
428  // -2 mHz ( int )( ( -2 + 3 ) / 3 ) = 0
429  // -1 mHz ( int )( ( -1 + 3 ) / 3 ) = 0 / 10e-3 = 10e( 3 * 0 - 3 )
430  // 0 Hz ( int )( ( 0 + 3 ) / 3 ) = 1
431  // 1 Hz ( int )( ( 1 + 3 ) / 3 ) = 1
432  // 2 Hz ( int )( ( 2 + 3 ) / 3 ) = 1 / 1e0 = 10e( 3 * 1 - 3 )
433  // 3 kHz ( int )( ( 3 + 3 ) / 3 ) = 2
434  // 4 kHz ( int )( ( 4 + 3 ) / 3 ) = 2
435  // 5 kHz ( int )( ( 5 + 3 ) / 3 ) = 2 / 10e3 = 10e( 3 * 2 - 3 )
436  // 6 MHz ( int )( ( 6 + 3 ) / 3 ) = 3
437  // 7 MHz ( int )( ( 7 + 3 ) / 3 ) = 3
438  // 8 MHz ( int )( ( 8 + 3 ) / 3 ) = 3 / 10e6 =10e( 3 * 3 - 3 )
439 
440  // unit string
441  static const char *unit_str[] =
442  {
443  "mHz",
444  "Hz",
445  "kHz",
446  "MHz"
447  };
448 
449 
450  if ( p_ff->khz_val )
451  {
452  // calculate frequency in Hz
453  freq = ( double ) p_ff->khz_val * pow( 10, ( p_ff->range + 3 ) );
454 
455  // calculate decimal exponent
456  range = ( ( int ) log10( freq ) );
457 
458  // check whether range is in the allowed range
459  // if so display frequency in broken format
460  if ( ( range >= -3 ) && ( range <= 8 ) )
461  {
462  // calculate format index ( see above )
463  format = ( ( ( range % 3 ) + 3 ) % 3 );
464 
465  // calculate unit index
466  unit = ( ushort )( range + 3 ) / 3;
467 
468  // calculate display value
469  freq = freq / pow( 10, ( ( 3 * unit ) - 3 ) );
470  n = snprintf_safe( s, max_len, fmt_str[format], freq, unit_str[unit] );
471  }
472  else
473  {
474  // out of range display fequency in Hz
475  n = snprintf_safe( s, max_len, "%fHz", freq );
476  }
477  }
478  else
479  n = sn_cpy_str_safe( s, max_len, str_na );
480 
481  return n;
482 
483 } // snprint_fixed_freq
484 
485 #endif // _USE_GPSUTILS_FULL
486 
double deltan
+- Mean Motion Diff. from computed value [rad/sec]
Definition: gpsdefs.h:18455
DMS longitude
Longitude broken down to degrees, minutes, seconds.
Definition: mbggeo.h:117
size_t snprint_alt(char *s, size_t max_len, double alt)
Print the altitude part of a geo position into a string buffer.
double A1
+- Clock Correction Coefficient 1 [sec/sec]
Definition: gpsdefs.h:18571
Ephemeris parameters of one specific satellite.
Definition: gpsdefs.h:18436
A structure used to hold a fixed frequency value.
Definition: gpsdefs.h:846
GPS UTC correction parameters.
Definition: gpsdefs.h:18564
int16_t range
an optional base 10 exponent
Definition: gpsdefs.h:849
double beta_0
Ionosph. Corr. Coeff. Beta 0 [sec].
Definition: gpsdefs.h:18607
double af2
+- Clock Correction Coefficient 2 [sec/sec^2]
Definition: gpsdefs.h:18467
double e
Eccentricity [—].
Definition: gpsdefs.h:18450
#define DEG
Definition: charcode.h:197
double af1
+- Clock Correction Coefficient 1 [sec/sec]
Definition: gpsdefs.h:18466
unsigned short uint16_t
Definition: words.h:213
double alpha_2
Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2].
Definition: gpsdefs.h:18604
double alpha_1
Ionosph. Corr. Coeff. Alpha 1 [sec/deg].
Definition: gpsdefs.h:18603
int sn_cpy_str_safe(char *dst, size_t max_len, const char *src)
A function to copy a string safely, returning the number of characters copied.
Definition: str_util.c:276
double crs
+- Sine Corr. Term to Orbit Radius [m]
Definition: gpsdefs.h:18459
DMS latitude
Latitude broken down to degrees, minutes, seconds.
Definition: mbggeo.h:118
void swap_iono_doubles(IONO *p)
Swap the "double" fields in a IONO structure.
Definition: gpsutils.c:235
void swap_eph_doubles(EPH *p)
Swap the "double" fields in an EPH structure.
Definition: gpsutils.c:138
double af0
+- Clock Correction Coefficient 0 [sec]
Definition: gpsdefs.h:18465
double OMEGA0
+- Longit. of Asc. Node of orbit plane [rad]
Definition: gpsdefs.h:18499
double tgd
+- estimated group delay differential [sec]
Definition: gpsdefs.h:18468
double cuc
+- Cosine Corr. Term to Arg. of Latitude [rad]
Definition: gpsdefs.h:18460
double beta_2
Ionosph. Corr. Coeff. Beta 2 [sec/deg^2].
Definition: gpsdefs.h:18609
unsigned short ushort
Definition: words.h:282
double beta_1
Ionosph. Corr. Coeff. Beta 1 [sec/deg].
Definition: gpsdefs.h:18608
Definition: gpsdefs.h:2754
double alpha_3
Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3].
Definition: gpsdefs.h:18605
double A0
+- Clock Correction Coefficient 0 [sec]
Definition: gpsdefs.h:18570
double idot
+- Rate of Inclination Angle [rad/sec]
Definition: gpsdefs.h:18457
Geographic longitude or latitude in [degrees, minutes, seconds].
Definition: mbggeo.h:90
double sqrt_A
Square Root of semi-major Axis [sqrt(m)].
Definition: gpsdefs.h:18494
void swap_alm_doubles(ALM *p)
Swap the "double" fields in an ALM structure.
Definition: gpsutils.c:182
size_t snprint_dms(char *s, size_t max_len, const DMS *p, int prec)
Print the DMS part of a geo position into a string buffer.
uint16_t prefix
&#39;N&#39;, &#39;E&#39;, &#39;S&#39; or &#39;W&#39;
Definition: mbggeo.h:92
Ionospheric correction parameters.
Definition: gpsdefs.h:18597
double alpha_0
Ionosph. Corr. Coeff. Alpha 0 [sec].
Definition: gpsdefs.h:18602
double OMEGADOT
+- Rate of Right Ascension [rad/sec]
Definition: gpsdefs.h:18454
uint16_t deg
[0...90 (lat) or 0...180 (lon)]
Definition: mbggeo.h:93
double af0
+- Clock Correction Coefficient 0 [sec]
Definition: gpsdefs.h:18502
double OMEGA0
+- Longit. of Asc. Node of orbit plane [rad]
Definition: gpsdefs.h:18453
void swap_utc_doubles(UTC *p)
Swap the "double" fields in a UTC structure.
Definition: gpsutils.c:212
double M0
+- Mean Anomaly at Ref. Time [rad]
Definition: gpsdefs.h:18497
size_t snprint_pos_geo(char *s, size_t max_len, const POS *p, char sep, int prec)
Print a geo position in POS format into a string buffer.
Almanac parameters of one specific satellite.
Definition: gpsdefs.h:18486
double crc
+- Cosine Corr. Term to Orbit Radius [m]
Definition: gpsdefs.h:18458
double deltai
+- [rad]
Definition: gpsdefs.h:18501
double e
Eccentricity [—].
Definition: gpsdefs.h:18495
A geographic position represented in different formats.
Definition: mbggeo.h:113
XYZ xyz
Always WGS84 ECEF coordinates.
Definition: mbggeo.h:115
double beta_3
Ionosph. Corr. Coeff. Beta 3 [sec/deg^3].
Definition: gpsdefs.h:18610
void swap_double(double *p)
Swap the bytes of a single variable of type "double".
Definition: gpsutils.c:101
double af1
+- Clock Correction Coefficient 1 [sec/sec]
Definition: gpsdefs.h:18503
double sqrt_A
Square Root of semi-major Axis [sqrt(m)].
Definition: gpsdefs.h:18449
size_t snprint_fixed_freq(char *s, size_t max_len, FIXED_FREQ_INFO *p_ff)
Print a formatted FIXED_FREQ_INFO into a string buffer.
uint16_t min
[0...59]
Definition: mbggeo.h:94
double OMEGADOT
+- Rate of Right Ascension [rad/sec]
Definition: gpsdefs.h:18500
double M0
+- Mean Anomaly at Ref. Time [rad]
Definition: gpsdefs.h:18451
LLA lla
Longitude, latitude and altitude, depending on the ellipsoid used for reference.
Definition: mbggeo.h:116
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
Definition: str_util.c:156
double omega
+- Argument of Perigee [rad]
Definition: gpsdefs.h:18498
double sec
[0...59.99999...]
Definition: mbggeo.h:95
void swap_pos_doubles(POS *p)
Swap the "double" fields in a POS structure.
Definition: gpsutils.c:265
double cis
+- Sine Corr. Term to Inclination Angle [rad]
Definition: gpsdefs.h:18463
double cus
+- Sine Corr. Term to Arg. of Latitude [rad]
Definition: gpsdefs.h:18461
double cic
+- Cosine Corr. Term to Inclination Angle [rad]
Definition: gpsdefs.h:18462
uint16_t khz_val
the base frequency in [kHz]
Definition: gpsdefs.h:848
double omega
+- Argument of Perigee [rad]
Definition: gpsdefs.h:18452
Definition: gpsdefs.h:2754
double i0
+- Inclination Angle [rad]
Definition: gpsdefs.h:18456
Definition: gpsdefs.h:2754