2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <osmocore/utils.h>
32 #include <osmocom/bb/common/osmocom_data.h>
33 #include <osmocom/bb/common/logging.h>
34 #include <osmocom/bb/common/gps.h>
36 struct osmo_gps gps = {
46 static struct bsc_fd gps_bfd;
47 static struct termios gps_termios, gps_old_termios;
49 static int osmo_gps_line(char *line)
51 time_t gps_now, host_now;
54 double latitude, longitude;
56 if (!!strncmp(line, "$GPGLL", 6))
59 if (strlen(line) < 37)
62 /* ddmm.mmmm,N,dddmm.mmmm,E,hhmmss.mmm,A */
65 if (line[36] != 'A') {
66 LOGP(DGPS, LOGL_INFO, "%s (invalid)\n", line);
73 gps_now = line[30] - '0';
74 gps_now += (line[29] - '0') * 10;
75 gps_now += (line[28] - '0') * 60;
76 gps_now += (line[27] - '0') * 600;
77 gps_now += (line[26] - '0') * 3600;
78 gps_now += (line[25] - '0') * 36000;
80 /* calculate the number of seconds the host differs from GPS */
81 diff = host_now % 86400 - gps_now;
86 /* apply the "date" part to the GPS time */
87 gps_now = host_now - diff;
89 tm = localtime(&gps_now);
92 latitude = (double)(line[0] - '0') * 10.0;
93 latitude += (double)(line[1] - '0');
94 latitude += (double)(line[2] - '0') / 6.0;
95 latitude += (double)(line[3] - '0') / 60.0;
96 latitude += (double)(line[5] - '0') / 600.0;
97 latitude += (double)(line[6] - '0') / 6000.0;
98 latitude += (double)(line[7] - '0') / 60000.0;
99 latitude += (double)(line[8] - '0') / 600000.0;
101 latitude = 0.0 - latitude;
102 gps.latitude = latitude;
103 longitude = (double)(line[12] - '0') * 100.0;
104 longitude += (double)(line[13] - '0') * 10.0;
105 longitude += (double)(line[14] - '0');
106 longitude += (double)(line[15] - '0') / 6.0;
107 longitude += (double)(line[16] - '0') / 60.0;
108 longitude += (double)(line[18] - '0') / 600.0;
109 longitude += (double)(line[19] - '0') / 6000.0;
110 longitude += (double)(line[20] - '0') / 60000.0;
111 longitude += (double)(line[21] - '0') / 600000.0;
113 longitude = 360.0 - longitude;
114 gps.longitude = longitude;
116 LOGP(DGPS, LOGL_DEBUG, "%s\n", line);
117 LOGP(DGPS, LOGL_INFO, " time=%02d:%02d:%02d %04d-%02d-%02d, "
118 "diff-to-host=%d, latitude=%do%.4f, longitude=%do%.4f\n",
119 tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900,
120 tm->tm_mday, tm->tm_mon + 1, diff,
122 (gps.latitude - ((int)gps.latitude)) * 60.0,
124 (gps.longitude - ((int)gps.longitude)) * 60.0);
128 static int nmea_checksum(char *line)
130 uint8_t checksum = 0;
141 return (strtoul(line+1, NULL, 16) == checksum);
144 int osmo_gps_cb(struct bsc_fd *bfd, unsigned int what)
147 static char line[128];
151 len = read(bfd->fd, buff, sizeof(buff));
153 fprintf(stderr, "error reading GPS device (errno=%d)\n", errno);
165 if (!nmea_checksum(line))
166 fprintf(stderr, "NMEA checksum error\n");
171 line[lpos++] = buff[i++];
172 if (lpos == sizeof(line))
179 int osmo_gps_open(void)
186 LOGP(DGPS, LOGL_INFO, "Open GPS device '%s'\n", gps.device);
189 gps_bfd.when = BSC_FD_READ;
190 gps_bfd.cb = osmo_gps_cb;
191 gps_bfd.fd = open(gps.device, O_RDONLY);
201 baud = B19200; break;
203 baud = B38400; break;
205 baud = B57600; break;
207 baud = B115200; break;
210 if (isatty(gps_bfd.fd))
213 tcgetattr(gps_bfd.fd, &gps_old_termios);
214 tcgetattr(gps_bfd.fd, &gps_termios);
217 gps_termios.c_cflag |= baud;
218 cfsetispeed(&gps_termios, baud);
219 cfsetospeed(&gps_termios, baud);
221 if (tcsetattr(gps_bfd.fd, TCSANOW, &gps_termios))
222 printf("Failed to set termios for GPS\n");
225 bsc_register_fd(&gps_bfd);
230 void osmo_gps_close(void)
235 LOGP(DGPS, LOGL_INFO, "Close GPS device\n");
237 bsc_unregister_fd(&gps_bfd);
239 if (isatty(gps_bfd.fd))
240 tcsetattr(gps_bfd.fd, TCSANOW, &gps_old_termios);
243 gps_bfd.fd = -1; /* -1 or 0 indicates: 'close' */
246 void osmo_gps_init(void)
248 memset(&gps_bfd, 0, sizeof(gps_bfd));