Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
231 killagreg 1
#include <inttypes.h>
2
 
3
#include "ubx.h"
4
#include <avr/io.h>
5
 
6
 
7
// ubx protocol parser state machine
8
#define UBXSTATE_IDLE   0
9
#define UBXSTATE_SYNC1  1
10
#define UBXSTATE_SYNC2  2
11
#define UBXSTATE_CLASS  3
12
#define UBXSTATE_LEN1   4
13
#define UBXSTATE_LEN2   5
14
#define UBXSTATE_DATA   6
15
#define UBXSTATE_CKA    7
16
#define UBXSTATE_CKB    8
17
 
18
// ublox protocoll identifier
19
#define UBX_CLASS_NAV   0x01
20
 
21
#define UBX_ID_POSLLH   0x02
22
#define UBX_ID_SOL              0x06
23
#define UBX_ID_VELNED   0x12
24
 
25
#define UBX_SYNC1_CHAR  0xB5
26
#define UBX_SYNC2_CHAR  0x62
27
 
28
typedef struct {
29
        uint32_t                ITOW;           // ms GPS Millisecond Time of Week
30
        int32_t                 Frac;           // ns remainder of rounded ms above
31
        int16_t                 week;           // GPS week
32
        uint8_t                 GPSfix;         // GPSfix Type, range 0..6
33
        uint8_t                 Flags;          // Navigation Status Flags
34
        int32_t                 ECEF_X;         // cm ECEF X coordinate
35
        int32_t                 ECEF_Y;         // cm ECEF Y coordinate
36
        int32_t                 ECEF_Z;         // cm ECEF Z coordinate
37
        uint32_t                PAcc;           // cm 3D Position Accuracy Estimate
38
        int32_t                 ECEFVX;         // cm/s ECEF X velocity
39
        int32_t                 ECEFVY;         // cm/s ECEF Y velocity
40
        int32_t                 ECEFVZ;         // cm/s ECEF Z velocity
41
        uint32_t                SAcc;           // cm/s Speed Accuracy Estimate
42
        uint16_t                PDOP;           // 0.01 Position DOP
43
        uint8_t                 res1;           // reserved
44
        uint8_t                 numSV;          // Number of SVs used in navigation solution
45
        uint32_t                res2;           // reserved
46
        Status_t                Status;
47
} UBX_SOL_t;
48
 
49
typedef struct {
50
        uint32_t                ITOW;           // ms GPS Millisecond Time of Week
51
        int32_t                 LON;            // 1e-07 deg Longitude
52
        int32_t                 LAT;            // 1e-07 deg Latitude
53
        int32_t                 HEIGHT;         // mm Height above Ellipsoid
54
        int32_t                 HMSL;           // mm Height above mean sea level
55
        uint32_t                Hacc;           // mm Horizontal Accuracy Estimate
56
        uint32_t                Vacc;           // mm Vertical Accuracy Estimate
57
        Status_t                Status;
58
} UBX_POSLLH_t;
59
 
60
typedef struct {
61
        uint32_t                ITOW;           // ms  GPS Millisecond Time of Week
62
        int32_t                 VEL_N;          // cm/s  NED north velocity
63
        int32_t                 VEL_E;          // cm/s  NED east velocity
64
        int32_t                 VEL_D;          // cm/s  NED down velocity
65
        uint32_t                Speed;          // cm/s  Speed (3-D)
66
        uint32_t                GSpeed;         // cm/s  Ground Speed (2-D)
67
        int32_t                 Heading;        // 1e-05 deg  Heading 2-D
68
        uint32_t                SAcc;           // cm/s  Speed Accuracy Estimate
69
        uint32_t                CAcc;           // deg  Course / Heading Accuracy Estimate
70
        Status_t                Status;
71
} UBX_VELNED_t;
72
 
73
UBX_SOL_t               UbxSol    = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, INVALID};
74
UBX_POSLLH_t    UbxPosLlh = {0,0,0,0,0,0,0, INVALID};
75
UBX_VELNED_t    UbxVelNed = {0,0,0,0,0,0,0,0,0, INVALID};
76
GPS_INFO_t      GPSInfo   = {0,0,0,0,0,0,0,0,0,0, INVALID};
77
 
78
volatile uint8_t GPSTimeout = 0;
79
 
80
void UpdateGPSInfo (void)
81
{
82
 
83
        if ((UbxSol.Status == NEWDATA) && (UbxPosLlh.Status == NEWDATA) && (UbxVelNed.Status == NEWDATA))
84
        {
85
                if(GPSInfo.status != NEWDATA)
86
                {
87
                        GPSInfo.status = INVALID;
88
                        // NAV SOL
89
                        GPSInfo.flags = UbxSol.Flags;
90
                        GPSInfo.satfix = UbxSol.GPSfix;
91
                        GPSInfo.satnum = UbxSol.numSV;
92
                        GPSInfo.PAcc = UbxSol.PAcc;
93
                        GPSInfo.VAcc = UbxSol.SAcc;
94
                        // NAV POSLLH
95
                        GPSInfo.longitude = UbxPosLlh.LON;
96
                        GPSInfo.latitude = UbxPosLlh.LAT;
97
                        GPSInfo.altitude = UbxPosLlh.HEIGHT;
98
 
99
                        GPSInfo.veleast = UbxVelNed.VEL_E;
100
                        GPSInfo.velnorth = UbxVelNed.VEL_N;
101
                        GPSInfo.veltop = -UbxVelNed.VEL_D;
102
                        GPSInfo.velground = UbxVelNed.GSpeed;
103
 
104
                        GPSInfo.status = NEWDATA;
105
 
106
                }
107
                // set state to collect new data
108
                UbxSol.Status = PROCESSED;                      // never update old data
109
                UbxPosLlh.Status = PROCESSED;           // never update old data
110
                UbxVelNed.Status = PROCESSED;           // never update old data
111
        }
112
 
113
 
114
}
115
 
116
 
117
// this function should be called within the UART RX ISR
118
void ubx_parser(uint8_t c)
119
{
120
        static uint8_t ubxstate = UBXSTATE_IDLE;
121
        static uint8_t cka, ckb;
122
        static uint16_t msglen;
123
        static int8_t *ubxP, *ubxEp, *ubxSp; // pointers to data currently transfered
124
 
125
        switch(ubxstate)
126
        {
127
                case UBXSTATE_IDLE: // check 1st sync byte
128
                        if (c == UBX_SYNC1_CHAR) ubxstate = UBXSTATE_SYNC1;
129
                        else ubxstate = UBXSTATE_IDLE; // out of synchronization
130
                        break;
131
 
132
                case UBXSTATE_SYNC1: // check 2nd sync byte
133
                        if (c == UBX_SYNC2_CHAR) ubxstate = UBXSTATE_SYNC2;
134
                        else ubxstate = UBXSTATE_IDLE; // out of synchronization
135
                        break;
136
 
137
                case UBXSTATE_SYNC2: // check msg class to be NAV
138
                        if (c == UBX_CLASS_NAV) ubxstate = UBXSTATE_CLASS;
139
                        else ubxstate = UBXSTATE_IDLE; // unsupported message class
140
                        break;
141
 
142
                case UBXSTATE_CLASS: // check message identifier
143
                        switch(c)
144
                        {
145
                                case UBX_ID_POSLLH: // geodetic position
146
                                        ubxP =  (int8_t *)&UbxPosLlh; // data start pointer
147
                                        ubxEp = (int8_t *)(&UbxPosLlh + 1); // data end pointer
148
                                        ubxSp = (int8_t *)&UbxPosLlh.Status; // status pointer
149
                                        break;
150
 
151
                                case UBX_ID_SOL: // navigation solution
152
                                        ubxP =  (int8_t *)&UbxSol; // data start pointer
153
                                        ubxEp = (int8_t *)(&UbxSol + 1); // data end pointer
154
                                        ubxSp = (int8_t *)&UbxSol.Status; // status pointer
155
                                        break;
156
 
157
                                case UBX_ID_VELNED: // velocity vector in tangent plane
158
                                        ubxP =  (int8_t *)&UbxVelNed; // data start pointer
159
                                        ubxEp = (int8_t *)(&UbxVelNed + 1); // data end pointer
160
                                        ubxSp = (int8_t *)&UbxVelNed.Status; // status pointer
161
                                        break;
162
 
163
                                default:                        // unsupported identifier
164
                                        ubxstate = UBXSTATE_IDLE;
165
                                        break;
166
                        }
167
                        if (ubxstate != UBXSTATE_IDLE)
168
                        {
169
                                ubxstate = UBXSTATE_LEN1;
170
                                cka = UBX_CLASS_NAV + c;
171
                                ckb = UBX_CLASS_NAV + cka;
172
                        }
173
                        break;
174
 
175
                case UBXSTATE_LEN1: // 1st message length byte
176
                        msglen = c;
177
                        cka += c;
178
                        ckb += cka;
179
                        ubxstate = UBXSTATE_LEN2;
180
                        break;
181
 
182
                case UBXSTATE_LEN2: // 2nd message length byte
183
                        msglen += ((uint16_t)c)<<8;
184
                        cka += c;
185
                        ckb += cka;
186
                        // if the old data are not processed so far then break parsing now
187
                        // to avoid writing new data in ISR during reading by another function
188
                        if ( *ubxSp == NEWDATA )
189
                        {
190
                                UpdateGPSInfo(); //update GPS info respectively
191
                                ubxstate = UBXSTATE_IDLE;
192
                        }
193
                        else // data invalid or allready processd
194
                        {
195
                                *ubxSp = INVALID;
196
                                ubxstate = UBXSTATE_DATA;
197
                        }
198
                        break;
199
 
200
                case UBXSTATE_DATA:
201
                        if (ubxP < ubxEp) *ubxP++ = c; // copy curent data byte if any space is left
202
                        cka += c;
203
                        ckb += cka;
204
                        if (--msglen == 0)      ubxstate = UBXSTATE_CKA; // switch to next state if all data was read
205
                        break;
206
 
207
                case UBXSTATE_CKA:
208
                        if (c == cka) ubxstate = UBXSTATE_CKB;
209
                        else
210
                        {
211
                                *ubxSp = INVALID;
212
                                ubxstate = UBXSTATE_IDLE;
213
                        }
214
                        break;
215
 
216
                case UBXSTATE_CKB:
217
                        if (c == ckb)
218
                        {
219
                                *ubxSp = NEWDATA; // new data are valid
220
                                UpdateGPSInfo(); //update GPS info respectively
221
                                GPSTimeout = 255;
222
                        }
223
                        else
224
                        {       // if checksum not fit then set data invalid
225
                                *ubxSp = INVALID;
226
                        }
227
                        ubxstate = UBXSTATE_IDLE; // ready to parse new data
228
                        break;
229
 
230
                default: // unknown ubx state
231
                        ubxstate = UBXSTATE_IDLE;
232
                        break;
233
        }
234
 
235
}
236
 
237