Subversion Repositories shark

Rev

Rev 1655 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1655 giacomo 1
#include <kernel/kern.h>
2
#include <math.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include "nmea.h"
6
 
7
extern struct OUTDATA gNMEAdata;
8
static void do_lat_lon(char *sentence, int begin);
9
static void do_grid(void);
10
static char *field(char *sentence, short n);
11
static void update_field_i(char *sentence, int fld, int *dest, int mask);
12
 
13
void processGPRMC(char *sentence)
14
{
15
    char s[20], d[10];
16
    int tmp;
17
 
18
    sscanf(field(sentence, 9), "%s", d);        /* Date: ddmmyy */
19
 
20
    strncpy(s, d + 2, 2);       /* copy month */
21
 
22
    strncpy(s + 3, d, 2);       /* copy date */
23
 
24
    sscanf((d+4), "%2d", &tmp);
25
 
26
    /* Tf.: Window the year from 1970 to 2069. This buys us some time. */
27
    if (tmp < 70)
28
      strncpy(s + 6, "20", 2);  /* 21th century */
29
    else
30
      strncpy(s + 6, "19", 2);  /* 20th century */
31
 
32
    strncpy(s + 8, d + 4, 2);   /* copy year */
33
 
34
    sscanf(field(sentence, 1), "%s", d);        /* Time: hhmmss */
35
 
36
    strncpy(s + 11, d, 2);      /* copy hours */
37
 
38
    strncpy(s + 14, d + 2, 2);  /* copy minutes */
39
 
40
    strncpy(s + 17, d + 4, 2);  /* copy seconds */
41
 
42
    s[2] = s[5] = '/';          /* add the '/'s, ':'s, ' ' and string terminator */
43
 
44
    s[10] = ' ';
45
    s[13] = s[16] = ':';
46
    s[19] = '\0';
47
 
48
    strcpy(gNMEAdata.utc, s);
49
 
50
    /* A = valid, V = invalid */
51
    if (strcmp(field(sentence, 2), "V") == 0)
52
        gNMEAdata.status = 0;
53
#if 0    /* Let the GGA sentence do the update so we catch diff fixes */
54
    else
55
        gNMEAdata.status = 0;
56
#endif
57
 
58
    sscanf(field(sentence, 7), "%lf", &gNMEAdata.speed);
59
    sscanf(field(sentence, 8), "%lf", &gNMEAdata.track);
60
 
61
    do_lat_lon(sentence, 3);
62
    do_grid();
63
 
64
}
65
 
66
/* ----------------------------------------------------------------------- */
67
 
68
void processGPVTG(char *sentence)
69
{
70
    sscanf(field(sentence, 3), "%lf", &gNMEAdata.speed);
71
    sscanf(field(sentence, 1), "%lf", &gNMEAdata.track);
72
}
73
 
74
/* ----------------------------------------------------------------------- */
75
 
76
void processGPGGA(char *sentence)
77
{
78
    do_lat_lon(sentence, 2);
79
    do_grid();
80
    /* 0 = none, 1 = normal, 2 = diff */
81
    sscanf(field(sentence, 6), "%d", &gNMEAdata.status);
82
    if ((gNMEAdata.status > 0) && (gNMEAdata.mode < 2))
83
        gNMEAdata.mode = 2;
84
    if ((gNMEAdata.status < 1) && (gNMEAdata.mode > 1))
85
        gNMEAdata.mode = 1;
86
    sscanf(field(sentence, 7), "%d", &gNMEAdata.satellites);
87
    sscanf(field(sentence, 9), "%lf", &gNMEAdata.altitude);
88
}
89
 
90
/* ----------------------------------------------------------------------- */
91
 
92
void processGPGSA(char *sentence)
93
{
94
 
95
  /* 1 = none, 2 = 2d, 3 = 3d */
96
    sscanf(field(sentence, 2), "%d", &gNMEAdata.mode);
97
    if ((gNMEAdata.mode > 1) && (gNMEAdata.status < 1))
98
        gNMEAdata.status = 1;
99
    if ((gNMEAdata.mode < 2) && (gNMEAdata.status > 0))
100
        gNMEAdata.status = 0;
101
    sscanf(field(sentence, 15), "%lf", &gNMEAdata.pdop);
102
    sscanf(field(sentence, 16), "%lf", &gNMEAdata.hdop);
103
    sscanf(field(sentence, 17), "%lf", &gNMEAdata.vdop);
104
}
105
 
106
/* ----------------------------------------------------------------------- */
107
 
108
void processGPGSV(char *sentence)
109
{
110
    int n, m, f = 4;
111
 
112
 
113
    if (sscanf(field(sentence, 2), "%d", &n) < 1)
114
        return;
115
    update_field_i(sentence, 3, &gNMEAdata.in_view, C_SAT);
116
 
117
    n = (n - 1) * 4;
118
    m = n + 4;
119
 
120
    while (n < gNMEAdata.in_view && n < m) {
121
        update_field_i(sentence, f++, &gNMEAdata.PRN[n], C_SAT);
122
        update_field_i(sentence, f++, &gNMEAdata.elevation[n], C_SAT);
123
        update_field_i(sentence, f++, &gNMEAdata.azimuth[n], C_SAT);
124
        if (*(field(sentence, f)))
125
            update_field_i(sentence, f, &gNMEAdata.ss[n], C_SAT);
126
        f++;
127
        n++;
128
    }
129
}
130
 
131
/* ----------------------------------------------------------------------- */
132
 
133
void processPRWIZCH(char *sentence)
134
{
135
    int i;
136
 
137
    for (i = 0; i < 12; i++) {
138
        update_field_i(sentence, 2 * i + 1, &gNMEAdata.Zs[i], C_ZCH);
139
        update_field_i(sentence, 2 * i + 2, &gNMEAdata.Zv[i], C_ZCH);
140
    }
141
    gNMEAdata.ZCHseen = 1;
142
}
143
 
144
/* ----------------------------------------------------------------------- */
145
 
146
static void do_lat_lon(char *sentence, int begin)
147
{
148
    double lat, lon, d, m;
149
    char str[20], *p;
150
    int updated = 0;
151
 
152
 
153
    if (*(p = field(sentence, begin + 0)) != '\0') {
154
        strncpy(str, p, 20);
155
        sscanf(p, "%lf", &lat);
156
        m = 100.0 * modf(lat / 100.0, &d);
157
        lat = d + m / 60.0;
158
        p = field(sentence, begin + 1);
159
        if (*p == 'S')
160
            lat = -lat;
161
        if (gNMEAdata.latitude != lat) {
162
            gNMEAdata.latitude = lat;
163
            gNMEAdata.cmask |= C_LATLON;
164
        }
165
        updated++;
166
    }
167
    if (*(p = field(sentence, begin + 2)) != '\0') {
168
        strncpy(str, p, 20);
169
        sscanf(p, "%lf", &lon);
170
        m = 100.0 * modf(lon / 100.0, &d);
171
        lon = d + m / 60.0;
172
 
173
        p = field(sentence, begin + 3);
174
        if (*p == 'W')
175
            lon = -lon;
176
        if (gNMEAdata.longitude != lon) {
177
            gNMEAdata.longitude = lon;
178
            gNMEAdata.cmask |= C_LATLON;
179
        }
180
        updated++;
181
    }
182
    if (updated == 2)
183
        gNMEAdata.last_update = sys_gettime(NULL);
184
}
185
 
186
/* ----------------------------------------------------------------------- */
187
 
188
static void do_grid() {
189
  double lat, lon;
190
 
191
  lat = gNMEAdata.latitude;
192
  lon = gNMEAdata.longitude;
193
 
194
  gNMEAdata.grid[0] = 65 + (int)((180.0 + lon) / 20.0);
195
  gNMEAdata.grid[1] = 65 + (int)((90.0 + lat) / 10.0);
196
  gNMEAdata.grid[2] = 48 + (int)((180.0 + lon) / 2) % 10;
197
  gNMEAdata.grid[3] = 48 + (int)(90.0 + lat) % 10;
198
  gNMEAdata.grid[4] = 97 + ((int)(180.0 + lon) % 2) * 12 + (int)(((180.0 + lon) - (int)(180.0 + lon)) * 12);
199
  gNMEAdata.grid[5] = 97 + (int)(((90.0 + lat) - (int)(90.0 + lat)) * 24);
200
  gNMEAdata.grid[6] = '\0';
201
}
202
 
203
/* ----------------------------------------------------------------------- */
204
 
205
static void update_field_i(char *sentence, int fld, int *dest, int mask)
206
{
207
    int tmp;
208
 
209
    sscanf(field(sentence, fld), "%d", &tmp);
210
 
211
    if (tmp != *dest) {
212
        *dest = tmp;
213
        gNMEAdata.cmask |= mask;
214
    }
215
}
216
 
217
void process_message(char *sentence)
218
{
219
    if (checksum(sentence)) {
220
        if (strncmp(GPRMC, sentence, 5) == 0) {
221
            processGPRMC(sentence);
222
        } else if (strncmp(GPGGA, sentence, 5) == 0) {
223
            processGPGGA(sentence);
224
        } else if (strncmp(GPVTG, sentence, 5) == 0) {
225
            processGPVTG(sentence);
226
        } else if (strncmp(GPGSA, sentence, 5) == 0) {
227
            processGPGSA(sentence);
228
        } else if (strncmp(GPGSV, sentence, 5) == 0) {
229
            processGPGSV(sentence);
230
        } else if (strncmp(PRWIZCH, sentence, 7) == 0) {
231
            processPRWIZCH(sentence);
232
        } else {
233
            cprintf("Unknown sentence: \"%s\"\n",sentence);
234
        }
235
    } else {
236
        cprintf("Bad Checksum !\n");
237
    }
238
}
239
 
240
/* ----------------------------------------------------------------------- */
241
 
242
short checksum(char *sentence)
243
{
244
    unsigned char sum = '\0';
245
    char c, *p = sentence, csum[3];
246
 
247
    while ((c = *p++) != '*' && c != '\0')
248
        sum ^= c;
249
 
250
    sprintf(csum, "%02x", sum);
251
    return (strncmp(csum, p, 2) == 0);
252
}
253
 
254
void add_checksum(char *sentence)
255
{
256
    unsigned char sum = '\0';
257
    char c, *p = sentence;
258
 
259
    while ((c = *p++) != '*')
260
        sum ^= c;
261
 
262
    sprintf(p, "%02x\r\n", sum);
263
}
264
 
265
static char *field(char *sentence, short n)
266
{
267
    static char result[100];
268
    char *p = sentence;
269
 
270
    while (n-- > 0)
271
        while (*p++ != ',');
272
    strcpy(result, p);
273
    p = result;
274
    while (*p && *p != ',' && *p != '*' && *p != '\r')
275
        p++;
276
 
277
    *p = '\0';
278
    return result;
279
}