-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgps.c
140 lines (119 loc) · 3.01 KB
/
gps.c
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
/*
* gps.c
*
* Created on: Feb 16, 2019
* Author: TritionCubed
*
* The GPS module for the payload.
* Gives access to the UPUTRONICS breakout for MAX-M8C GPS
*
* Getting a serial interface to work on RPi v3 was very complicated.
* To get a working Serial port on /dev/ttyS0, use these commands:
*
* $ sudo -s
* $ echo "enable_uart=1" >> /boot/config.txt
* $ systemctl stop [email protected]
* $ systemctl disable [email protected]
*
* You can see the output using
* $ screen /dev/ttyS0
*
* The breakout uses the following pins:
*
* RPI Chip
* --------------------
* Pin 1 (3v3) VCC
* Pin 6 (GND) GND
* Pin 5 (SCL) SCL
* Pin 3 (SDA) SDA
*/
#include "gps.h"
#include "nmea.h"
#include <bcm2835.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/*
* Stub
*/
void gps_init() {
}
/*
* Stub
*/
void gps_close() {
}
/*
* Saves location data to the given
* location struct.
*/
void getLocation( loc_t *coord ) {
char buff[100]; //buffer for processing
uint8_t status = _EMPTY; //status indicator
gpgga_t gpgga; //GPGGA data
gprmc_t gprmc; //GPRMC data
int i;
while( status != _COMPLETED ) {
//reads a line of gps data
bcm2835_i2c_setSlaveAddress( GPS_ADDRESS );
//bcm2835_delay( 10 );
buff[0] = 0;
while( buff[0] != '$' ) {
bcm2835_i2c_read( buff, 1 );
}
i = 1;
while( i < 100 ) {
bcm2835_i2c_read( &(buff[i]), 1 );
if( buff[i] == 0xFF ) {
continue;
}
else if( buff[i] == '\n' ) {
buff[i] = 0;
break;
}
else {
i++;
}
}
buff[99] = 0;
//keep parsing location/velocity data until we have both from the same frame
switch( nmea_get_message_type( buff ) ) {
case NMEA_GPGGA:
nmea_parse_gpgga( buff, &gpgga );
gps_convert_deg_to_dec( &(gpgga.latitude), gpgga.lat, &(gpgga.longitude), gpgga.lon );
coord->latitude = gpgga.latitude;
coord->longitude = gpgga.longitude;
coord->altitude = gpgga.altitude;
status |= NMEA_GPGGA;
break;
case NMEA_GPRMC:
nmea_parse_gprmc( buff, &gprmc );
coord->speed = gprmc.speed;
coord->course = gprmc.course;
coord->hour = gprmc.hour;
coord->minute = gprmc.minute;
coord->second = gprmc.second;
status |= NMEA_GPRMC;
break;
}
}
}
/*
* Convert lat e lon to decimals (from deg)
*/
void gps_convert_deg_to_dec( double *latitude, char ns, double *longitude, char we ) {
double lat = ( ns == 'N' ) ? *latitude : -1 * (*latitude);
double lon = ( we == 'E' ) ? *longitude : -1 * (*longitude);
*latitude = gps_deg_dec( lat );
*longitude = gps_deg_dec( lon );
}
double gps_deg_dec( double deg_point ) {
double ddeg;
double sec = modf( deg_point, &ddeg ) * 60;
int deg = (int)( ddeg / 100 );
int min = (int)( deg_point - ( deg * 100 ) );
double absdlat = round( deg * 1000000. );
double absmlat = round( min * 1000000. );
double absslat = round( sec * 1000000. );
return round( absdlat + ( absmlat / 60 ) + ( absslat / 3600) ) / 1000000;
}