1 #include <u.h>
2 #include <libc.h>
3 #include "dat.h"
4
5 char *serial = "/dev/eia0";
6
7 int ttyfd, ctlfd, debug;
8 int baud = Baud;
9 char *baudstr = "b%dd1r1pns1l8i1w5";
10
11 Place where = {-(74.0 + 23.9191/60.0), 40.0 + 41.1346/60.0};
12
13 void setline(void);
14 void evermore80(Place, int);
15 void evermore89(int);
16 void evermore8e(void);
17
18 void
setline(void)19 setline(void){
20 char *serialctl;
21
22 serialctl = smprint("%sctl", serial);
23 if((ttyfd = open(serial, ORDWR)) < 0)
24 sysfatal("%s: %r", serial);
25 if((ctlfd = open(serialctl, OWRITE)) >= 0){
26 if(fprint(ctlfd, baudstr, baud) < 0)
27 sysfatal("%s: %r", serialctl);
28 }
29 free(serialctl);
30 }
31
32 enum {
33 GGAon = 0x01,
34 GLLon = 0x02,
35 GSAon = 0x04,
36 GSVon = 0x08,
37 RMCon = 0x10,
38 VTGon = 0x20,
39 CRCon = 0x40,
40 EMTon = 0x80
41 };
42
43 char*
putbyte(char * s,int v)44 putbyte(char *s, int v)
45 {
46 *s++ = v;
47 if((v & 0xff) == 0x10)
48 *s++ = v;
49 return s;
50 }
51
52 char*
putshort(char * s,int v)53 putshort(char *s, int v)
54 {
55 s = putbyte(s, v);
56 s = putbyte(s, v >> 8);
57 return s;
58 }
59
60 char*
putlong(char * s,long v)61 putlong(char *s, long v)
62 {
63 s = putbyte(s, v);
64 s = putbyte(s, v >> 8);
65 s = putbyte(s, v >> 16);
66 s = putbyte(s, v >> 24);
67 return s;
68 }
69
70 void
evermoresend(char * body,int l)71 evermoresend(char *body, int l)
72 {
73 char buf[8], *s;
74 int crc, i;
75
76 s = buf;
77 *s++ = 0x10; /* DCE */
78 *s++ = 0x02; /* STX */
79 s = putbyte(s, l); /* length */
80 write(ttyfd, buf, s-buf); /* write header */
81
82 write(ttyfd, body, l); /* write body */
83
84 crc = 0;
85 for(i = 0; i < l; i++)
86 crc += body[i]; /* calculate crc */
87 s = buf;
88 s = putbyte(s, crc); /* checksum */
89 *s++ = 0x10; /* DCE */
90 *s++ = 0x03; /* ETX */
91 write(ttyfd, buf, s-buf); /* write trailer */
92 }
93
94 void
evermore80(Place pl,int baud)95 evermore80(Place pl, int baud)
96 {
97 char buf[32], *s;
98 long now, seconds, week;
99
100 fprint(2, "Evermore80");
101
102 time(&now);
103 seconds = now - 315964800;
104 week = (seconds / (7*24*3600));
105 seconds = seconds % (7*24*3600);
106 s = buf;
107
108 s = putbyte(s, 0x80); /* message ID */
109 s = putshort(s, week); /* week number */
110 s = putlong(s, seconds*100); /* seconds */
111 s = putshort(s, pl.lat*10.0); /* latitude tenths degree */
112 s = putshort(s, pl.lon*10.0); /* longitude tenths degree */
113 s = putshort(s, 100); /* altitude meters */
114 s = putshort(s, 0); /* datumn ID */
115 s = putbyte(s, 2); /* warm start */
116 s = putbyte(s, GGAon|GSAon|GSVon|RMCon|CRCon);
117 switch(baud){
118 case 4800: s = putbyte(s, 0); break;
119 case 9600: s = putbyte(s, 1); break;
120 case 19200: s = putbyte(s, 2); break;
121 case 38400: s = putbyte(s, 3); break;
122 default:
123 sysfatal("Illegal baud rate");
124 }
125
126 evermoresend(buf, s - buf);
127 fprint(2, "\n");
128 }
129
130 void
evermore89(int baud)131 evermore89(int baud)
132 {
133 char buf[32], *s;
134
135 fprint(2, "Evermore89");
136 s = buf;
137 s = putbyte(s, 0x89); /* message ID */
138 s = putbyte(s, 0x01); /* set main serial port */
139 switch(baud){
140 case 4800: s = putbyte(s, 0x00); break;
141 case 9600: s = putbyte(s, 0x01); break;
142 case 19200: s = putbyte(s, 0x02); break;
143 case 38400: s = putbyte(s, 0x03); break;
144 default:
145 sysfatal("illegal baud rate %d", baud);
146 }
147
148 evermoresend(buf, s - buf);
149 fprint(2, "\n");
150 }
151
152 void
evermore8e(void)153 evermore8e(void)
154 {
155 char buf[32], *s;
156
157 fprint(2, "Evermore8e");
158 s = buf;
159 s = putbyte(s, 0x8e); /* message ID */
160 s = putbyte(s, GGAon|GSAon|GSVon|RMCon); /* all messages except GLL and VTG */
161 s = putbyte(s, 0x01); /* checksum on */
162 s = putbyte(s, 0x01); /* GGA update rate */
163 s = putbyte(s, 0x0b); /* GLL update rate */
164 s = putbyte(s, 0x0a); /* GSA update rate */
165 s = putbyte(s, 0x14); /* GSV update rate */
166 s = putbyte(s, 0x08); /* RMC update rate */
167 s = putbyte(s, 0x0d); /* VTG update rate */
168
169 evermoresend(buf, s - buf);
170 fprint(2, "\n");
171 }
172
173 void
main(int argc,char * argv[])174 main(int argc, char*argv[])
175 {
176 char *p;
177 Place pl;
178 int newbaud;
179
180 newbaud = -1;
181 pl = nowhere;
182 ARGBEGIN {
183 default:
184 fprint(2, "usage: %s [-b baud] [-d device] [-l longitude latitude] [-n newbaud]\n", argv0);
185 exits("usage");
186 case 'D':
187 debug++;
188 break;
189 case 'b':
190 baud = strtol(ARGF(), nil, 0);
191 break;
192 case 'd':
193 serial = ARGF();
194 break;
195 case 'l':
196 p = ARGF();
197 if(strtolatlon(p, &p, &pl) < 0)
198 sysfatal("bad position");
199 while(*p == ' ' || *p == '\t' || *p == '\n')
200 p++;
201 if(*p == '\0')
202 p = ARGF();
203 if (strtolatlon(p, &p, &pl) < 0)
204 sysfatal("bad position");
205 while(*p == ' ' || *p == '\t' || *p == '\n')
206 p++;
207 if(*p != '\0')
208 sysfatal("trailing gunk in position");
209 where = pl;
210 break;
211 case 'n':
212 newbaud = strtol(ARGF(), nil, 0);
213 break;
214 } ARGEND
215
216 if(newbaud < 0)
217 newbaud = baud;
218
219 fmtinstall('L', placeconv);
220 print("Initializing GPS to %d baud, at %L, time %s\n",
221 newbaud, where, ctime(time(nil)));
222 setline();
223 evermore80(where, newbaud);
224 }
225