summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2005-02-11 11:29:57 +0000
committerEric S. Raymond <esr@thyrsus.com>2005-02-11 11:29:57 +0000
commit9f1c8194945b17f57afa1954d8487a3aaf51523f (patch)
tree42634d333ce83ec120013515e0049def7ead993e
parent58d5c0514b7126faeb13e4a51f79466a9140ebec (diff)
downloadgpsd-9f1c8194945b17f57afa1954d8487a3aaf51523f.tar.gz
Clean up and integrate Arnin's SiRF control code.
-rw-r--r--AUTHORS1
-rw-r--r--Makefile.am3
-rw-r--r--nmea_parse.c2
-rw-r--r--sirf.c257
-rw-r--r--sirf.h18
5 files changed, 279 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index 934cc9d3..f8b5a906 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,3 +2,4 @@ Remco Treffkorn <remco@rvt.com>
Derrick J. Brashear <shadow@dementia.org>
Russ Nelson <nelson@crynwyr.com>
Eric S. Raymond <esr@thyrsus.com>
+Arnim Laeuger <arnim.laeuger@gmx.net>
diff --git a/Makefile.am b/Makefile.am
index efb78276..9ff8d187 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,6 +54,7 @@ libgps_la_SOURCES = \
zodiac.c \
libgpsd_core.c \
libgps.c \
+ sirf.c \
report.c
libgps_la_LIBADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET)
@@ -95,7 +96,7 @@ release: distdir
BZIP2=$(BZIP2_ENV) $(AMTAR)$(TAR) --bzip2 -chof $(distdir).tar.bz2 $(distdir)
-rm -rf $(distdir)
-include_HEADERS = gps.h gpsd.h
+include_HEADERS = gps.h gpsd.h sirf.h
# Automake is buggy and doesn't automatically include bin_SCRIPTS in dist
EXTRA_DIST = \
diff --git a/nmea_parse.c b/nmea_parse.c
index f718e040..765bb34f 100644
--- a/nmea_parse.c
+++ b/nmea_parse.c
@@ -434,7 +434,7 @@ static short nmea_checksum(char *sentence, unsigned char *correct_sum)
**************************************************************************/
void nmea_add_checksum(char *sentence)
-/* add NMEA to a *-terminated sentence */
+/* add NMEA checksum to a *-terminated sentence */
{
unsigned char sum = '\0';
char c, *p = sentence;
diff --git a/sirf.c b/sirf.c
new file mode 100644
index 00000000..0542a341
--- /dev/null
+++ b/sirf.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2003 Arnim Laeuger <arnim.laeuger@gmx.net>
+ * Issued under GPL. Originally part of an unpublished utility
+ * called sirf_ctrl. Contributed to gpsd by the author.
+ *
+ * Modified to not use stderr and so each function returns 0 on success,
+ * nonzero on failure.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "sirf.h"
+
+static u_int8_t crc_nmea(char *msg) {
+ int pos;
+ char *tag;
+ u_int8_t crc = 0;
+ static char nib_to_hex[] = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+
+ /* ignore a leading '$' */
+ pos = msg[0] == '$' ? 1 : 0;
+
+ /* calculate CRC */
+ while (msg[pos] != '*' && msg[pos] != 0)
+ crc ^= msg[pos++];
+
+ /* set upper nibble of CRC */
+ tag = index(msg, '%');
+ *tag = nib_to_hex[(crc & 0xf0) >> 4];
+ /* set lower nibble of CRC */
+ tag = index(msg, '%');
+ *tag = nib_to_hex[crc & 0x0f];
+
+ return(crc);
+}
+
+
+static u_int16_t crc_sirf(u_int8_t *msg) {
+ int pos = 0;
+ u_int16_t crc = 0;
+ int len;
+
+ len = (msg[2] << 8) | msg[3];
+
+ /* calculate CRC */
+ while (pos != len)
+ crc += msg[pos++ + 4];
+ crc &= 0x7fff;
+
+ /* enter CRC after payload */
+ msg[len + 4] = (u_int8_t)((crc & 0xff00) >> 8);
+ msg[len + 5] = (u_int8_t)( crc & 0x00ff);
+
+ return(crc);
+}
+
+
+int sirf_to_sirfbin(int ttyfd) {
+ int len;
+ char msg[] = "$PSRF100,0,19200,8,1,0*%%\r\n";
+
+ crc_nmea(msg);
+
+ len = strlen(msg);
+ return (write(ttyfd, msg, len) != len);
+}
+
+
+int sirf_waas_ctrl(int ttyfd, int enable) {
+ u_int8_t msg[] = {0xa0, 0xa2, 0x00, 0x07,
+ 0x85, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ msg[5] = (u_int8_t)enable;
+ crc_sirf(msg);
+ return (write(ttyfd, msg, 15) != 15);
+}
+
+
+int sirf_to_nmea(int ttyfd) {
+ u_int8_t msg[] = {0xa0, 0xa2, 0x00, 0x18,
+ 0x81, 0x02,
+ 0x01, 0x01, /* GGA */
+ 0x00, 0x01, /* GLL */
+ 0x01, 0x01, /* GSA */
+ 0x05, 0x01, /* GSV */
+ 0x01, 0x01, /* RMC */
+ 0x00, 0x01, /* VTG */
+ 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x01,
+ 0x12, 0xc0,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ crc_sirf(msg);
+ return (write(ttyfd, msg, 0x18+8) != 0x18+8);
+}
+
+
+int sirf_reset(int ttyfd) {
+ u_int8_t msg[] = {0xa0, 0xa2, 0x00, 0x19,
+ 0x81,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ 0x0c,
+ 0x04,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ crc_sirf(msg);
+ return (write(ttyfd, msg, 0x19+8) != 0x19+8);
+}
+
+
+int sirf_dgps_source(int ttyfd, int source) {
+ int i;
+ u_int8_t msg1[] = {0xa0, 0xa2, 0x00, 0x07,
+ 0x85,
+ 0x00, /* DGPS source */
+ 0x00, 0x01, 0xe3, 0x34, /* 123.7 kHz */
+ 0x00, /* auto bitrate */
+ 0x00, 0x00, 0xb0, 0xb3};
+ u_int8_t msg2[] = {0xa0, 0xa2, 0x00, 0x03,
+ 0x8a,
+ 0x00, 0xff, /* auto, 255 sec */
+ 0x00, 0x00, 0xb0, 0xb3};
+ u_int8_t msg3[] = {0xa0, 0xa2, 0x00, 0x09,
+ 0x91,
+ 0x00, 0x00, 0x12, 0xc0, /* 4800 baud */
+ 0x08, /* 8 bits */
+ 0x01, /* 1 Stop bit */
+ 0x00, /* no parity */
+ 0x00,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ /*
+ * set DGPS source
+ */
+ switch (source) {
+ case DGPS_SOURCE_NONE:
+ /* set no DGPS source */
+ msg1[5] = 0x00;
+ break;
+ case DGPS_SOURCE_INTERNAL:
+ /* set to internal DGPS beacon */
+ msg1[5] = 0x03;
+ break;
+ case DGPS_SOURCE_WAAS:
+ /* set to WAAS/EGNOS */
+ msg1[5] = 0x01;
+ for (i = 6; i < 11; i++)
+ msg1[i] = 0x00;
+ break;
+ case DGPS_SOURCE_EXTERNAL:
+ /* set to external RTCM input */
+ msg1[5] = 0x02;
+ break;
+ }
+ crc_sirf(msg1);
+ if (write(ttyfd, msg1, 0x07+8) != 0x07+8)
+ return 1;
+
+ /*
+ * set DGPS control to auto
+ */
+ if (source != DGPS_SOURCE_WAAS) {
+ crc_sirf(msg2);
+ if (write(ttyfd, msg2, 0x03+8) != 0x03+8)
+ return 2;
+ }
+
+ /*
+ * set DGPS port
+ */
+ if (source == DGPS_SOURCE_EXTERNAL) {
+ crc_sirf(msg3);
+ if (write(ttyfd, msg3, 0x09+8) == 0x09+8)
+ return 3;
+ }
+
+ return(0);
+}
+
+
+int sirf_nav_lib (int ttyfd, int enable) {
+ u_int8_t msg_1[] = {0xa0, 0xa2, 0x00, 0x19,
+ 0x80,
+ 0x00, 0x00, 0x00, 0x00, /* ECEF X */
+ 0x00, 0x00, 0x00, 0x00, /* ECEF Y */
+ 0x00, 0x00, 0x00, 0x00, /* ECEF Z */
+ 0x00, 0x00, 0x00, 0x00, /* Clock Offset */
+ 0x00, 0x00, 0x00, 0x00, /* Time of Week */
+ 0x00, 0x00, /* Week Number */
+ 0x0c, /* Channels */
+ 0x00, /* Reset Config */
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ if (enable == 1)
+ msg_1[28] = 0x10;
+
+ crc_sirf(msg_1);
+ return (write(ttyfd, msg_1, 0x19+8) != 0x19+8);
+}
+
+
+int sirf_nmea_waas(int ttyfd, int enable) {
+ int len;
+ char msg[] = "$PSRF108,0?*%%\r\n";
+ char *tag;
+
+ tag = index(msg, '?');
+ *tag = enable == 1 ? '1' : '0';
+
+ crc_nmea(msg);
+
+ len = strlen(msg);
+ return (write(ttyfd, msg, len) != len);
+}
+
+
+int sirf_power_mask(int ttyfd, int low) {
+ u_int8_t msg[] = {0xa0, 0xa2, 0x00, 0x03,
+ 0x8c, 0x1c, 0x1c,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ if (low == 1)
+ msg[6] = 0x14;
+
+ crc_sirf(msg);
+ return (write(ttyfd, msg, 0x03+8) != 0x03+8);
+}
+
+
+int sirf_power_save(int ttyfd, int enable) {
+ u_int8_t msg[] = {0xa0, 0xa2, 0x00, 0x09,
+ 0x97,
+ 0x00, 0x00,
+ 0x03, 0xe8,
+ 0x00, 0x00, 0x00, 0xc8,
+ 0x00, 0x00, 0xb0, 0xb3};
+
+ if (enable == 1) {
+ /* power save: duty cycle is 20% */
+ msg[7] = 0x00;
+ msg[8] = 0xc8;
+ }
+
+ crc_sirf(msg);
+ return (write(ttyfd, msg, 0x09+8) != 0x09+8);
+}
diff --git a/sirf.h b/sirf.h
new file mode 100644
index 00000000..dd9fb865
--- /dev/null
+++ b/sirf.h
@@ -0,0 +1,18 @@
+/* sirf.h -- control functions for SiRF-II GPS chipset */
+
+#define DGPS_SOURCE_NONE 0
+#define DGPS_SOURCE_EXTERNAL 1
+#define DGPS_SOURCE_INTERNAL 2
+#define DGPS_SOURCE_WAAS 3
+
+int sirf_to_sirfbin(int);
+int sirf_waas_ctrl(int, int);
+int sirf_to_nmea(int);
+int sirf_reset(int);
+int sirf_dgps_source(int, int);
+int sirf_nav_lib(int, int);
+int sirf_nmea_waas(int, int);
+int sirf_power_mask(int, int);
+int sirf_power_save(int, int);
+
+/* sirf.h ends here */