summaryrefslogtreecommitdiff
path: root/sirf.c
blob: c69a13bb1f18c2a13d265de8a775447b4eb80f64 (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
/*
 * 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.  Alsso to use gpsd's own checksum and send code.
 */

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

#include "gpsd.h"
#include "sirf.h"

#ifdef __UNUSED__
/* These require binary mode */

#define HI(n)	((n) >> 8)
#define LO(n)	((n) & 0xff)

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_waas_ctrl(int ttyfd, int enable) 
/* enable or disable WAAS */
{
   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, int speed) 
/* switch from binary to NMEA at specified baud */
{
   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, /* 4800 bps */
                     0x00, 0x00, 0xb0, 0xb3};

   msg[26] = HI(speed);
   msg[27] = LO(speed);
   crc_sirf(msg);
   return (write(ttyfd, msg, 0x18+8) != 0x18+8);
}


int sirf_reset(int ttyfd) 
/* reset GPS parameters */
{
   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) 
/* set source for DGPS corrections */
{
   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)
/* set single-channel mode */
{
   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_power_mask(int ttyfd, int low)
/* set dB cutoff level below which satellite info will be ignored */
{
   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)
/* enable/disable SiRF trickle-power mode */ 
{
   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);
}

#endif /* __UNUSED __ */