Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
684 killagreg 1
#include <inttypes.h>
2
#include "ubx.h"
702 killagreg 3
#include "main.h"
4
#include <avr/io.h>
684 killagreg 5
 
722 killagreg 6
#include "uart.h"
7
#include "timer0.h"
8
 
684 killagreg 9
// ubx protocol parser state machine
10
#define UBXSTATE_IDLE   0
11
#define UBXSTATE_SYNC1  1
12
#define UBXSTATE_SYNC2  2
13
#define UBXSTATE_CLASS  3
14
#define UBXSTATE_LEN1   4
15
#define UBXSTATE_LEN2   5
16
#define UBXSTATE_DATA   6
17
#define UBXSTATE_CKA    7
18
#define UBXSTATE_CKB    8
19
 
20
// ublox protocoll identifier
21
#define UBX_CLASS_NAV   0x01
22
#define UBX_ID_POSLLH   0x02
23
#define UBX_ID_POSUTM   0x08
24
#define UBX_ID_STATUS   0x03
25
#define UBX_ID_VELNED   0x12
26
#define UBX_SYNC1_CHAR  0xB5
27
#define UBX_SYNC2_CHAR  0x62
28
 
29
 
30
typedef struct {
31
        uint32_t                ITOW;           // ms GPS Millisecond Time of Week
32
        uint8_t                 GPSfix;         // GPSfix Type, range 0..6
33
        uint8_t                 Flags;          // Navigation Status Flags
34
        uint8_t                 DiffS;          // Differential Status
35
        uint8_t                 res;            // reserved
36
        uint32_t                TTFF;           // Time to first fix (millisecond time tag)
37
        uint32_t                MSSS;           // Milliseconds since Startup / Reset
702 killagreg 38
        uint8_t                 Status;
684 killagreg 39
} GPS_STATUS_t;
40
 
41
typedef struct {
42
        uint32_t                ITOW;           // ms GPS Millisecond Time of Week
43
        int32_t                 LON;            // 1e-07 deg Longitude
44
        int32_t                 LAT;            // 1e-07 deg Latitude
45
        int32_t                 HEIGHT;         // mm Height above Ellipsoid
46
        int32_t                 HMSL;           // mm Height above mean sea level
47
        uint32_t                Hacc;           // mm Horizontal Accuracy Estimate
48
        uint32_t                Vacc;           // mm Vertical Accuracy Estimate
702 killagreg 49
        uint8_t                 Status;
684 killagreg 50
} GPS_POSLLH_t;
51
 
52
typedef struct {
53
        uint32_t                ITOW;           // ms GPS Millisecond Time of Week
54
        int32_t                 EAST;           // cm  UTM Easting
55
        int32_t                 NORTH;          // cm  UTM Nording
56
        int32_t                 ALT;            // cm  altitude
57
        uint8_t                 ZONE;           // UTM zone number
58
        uint8_t                 HEM;            // Hemisphere Indicator (0=North, 1=South)
702 killagreg 59
        uint8_t                 Status;
684 killagreg 60
} GPS_POSUTM_t;
61
 
62
typedef struct {
63
        uint32_t                ITOW;           // ms  GPS Millisecond Time of Week
64
        int32_t                 VEL_N;          // cm/s  NED north velocity
65
        int32_t                 VEL_E;          // cm/s  NED east velocity
66
        int32_t                 VEL_D;          // cm/s  NED down velocity
67
        uint32_t                Speed;          // cm/s  Speed (3-D)
68
        uint32_t                GSpeed;         // cm/s  Ground Speed (2-D)
69
        int32_t                 Heading;        // 1e-05 deg  Heading 2-D
70
        uint32_t                SAcc;           // cm/s  Speed Accuracy Estimate
71
        uint32_t                CAcc;           // deg  Course / Heading Accuracy Estimate
702 killagreg 72
        uint8_t                 Status;
684 killagreg 73
} GPS_VELNED_t;
74
 
75
 
76
GPS_STATUS_t    GpsStatus;
77
GPS_POSLLH_t    GpsPosLlh;
78
GPS_POSUTM_t    GpsPosUtm;
79
GPS_VELNED_t    GpsVelNed;
80
 
702 killagreg 81
GPS_INFO_t GPSInfo;
684 killagreg 82
 
83
void UpdateGPSInfo (void)
84
{
702 killagreg 85
        if (GpsStatus.Status == VALID)                  // valid packet
684 killagreg 86
        {
702 killagreg 87
                GPSInfo.satfix = GpsStatus.GPSfix;
88
                GpsStatus.Status = PROCESSED;                   // never update old data
684 killagreg 89
        }
702 killagreg 90
        if (GpsPosLlh.Status == VALID)                  // valid packet
684 killagreg 91
        {
702 killagreg 92
                GPSInfo.longitude = GpsPosLlh.LON;
93
                GPSInfo.latitude = GpsPosLlh.LAT;
94
                GPSInfo.altitude = GpsPosLlh.HEIGHT;
95
                GpsPosLlh.Status = PROCESSED;                   // never update old data
684 killagreg 96
        }
702 killagreg 97
        if (GpsPosUtm.Status == VALID)                  // valid packet
684 killagreg 98
        {
702 killagreg 99
                GPSInfo.utmeast = GpsPosUtm.EAST;
100
                GPSInfo.utmnorth = GpsPosUtm.NORTH;
101
                GPSInfo.utmalt = GpsPosUtm.ALT;
102
                GpsPosUtm.Status = PROCESSED;                   // never update old data
684 killagreg 103
        }
702 killagreg 104
        if (GpsVelNed.Status == VALID)                  // valid packet
684 killagreg 105
        {
702 killagreg 106
                GPSInfo.veleast = GpsVelNed.VEL_E;
107
                GPSInfo.velnorth = GpsVelNed.VEL_N;
108
                GPSInfo.veltop = -GpsVelNed.VEL_D;
109
                GpsPosUtm.Status = PROCESSED;                   // never update old data
684 killagreg 110
        }
722 killagreg 111
        if (GpsStatus.Status != INVALID)
702 killagreg 112
        {
722 killagreg 113
                GPSInfo.status = VALID;               // set valid if data are updated
702 killagreg 114
        }
684 killagreg 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_POSUTM: // utm position
146
                                        ubxP =  (int8_t *)&GpsPosUtm; // data start pointer
147
                                        ubxEp = (int8_t *)(&GpsPosUtm + sizeof(GPS_POSUTM_t)); // data end pointer
702 killagreg 148
                                        ubxSp = (int8_t *)&GpsPosUtm.Status; // status pointer
684 killagreg 149
                                        break;
150
 
151
                                case UBX_ID_POSLLH: // geodetic position
722 killagreg 152
                                        ubxP =  (int8_t *)&GpsPosLlh; // data start pointer
153
                                        ubxEp = (int8_t *)(&GpsPosLlh + sizeof(GPS_POSLLH_t)); // data end pointer
154
                                        ubxSp = (int8_t *)&GpsPosLlh.Status; // status pointer
684 killagreg 155
                                        break;
156
 
157
                                case UBX_ID_STATUS: // receiver status
158
                                        ubxP =  (int8_t *)&GpsStatus; // data start pointer
159
                                        ubxEp = (int8_t *)(&GpsStatus + sizeof(GPS_STATUS_t)); // data end pointer
702 killagreg 160
                                        ubxSp = (int8_t *)&GpsStatus.Status; // status pointer
684 killagreg 161
                                        break;
162
 
163
                                case UBX_ID_VELNED: // velocity vector in tangent plane
164
                                        ubxP =  (int8_t *)&GpsVelNed; // data start pointer
165
                                        ubxEp = (int8_t *)(&GpsVelNed + sizeof(GPS_VELNED_t)); // data end pointer
702 killagreg 166
                                        ubxSp = (int8_t *)&GpsVelNed.Status; // status pointer
684 killagreg 167
                                        break;
168
 
169
                                default:                        // unsupported identifier
170
                                        ubxstate = UBXSTATE_IDLE;
171
                                        break;
172
                        }
173
                        if (ubxstate != UBXSTATE_IDLE)
174
                        {
175
                                ubxstate = UBXSTATE_LEN1;
176
                                cka = UBX_CLASS_NAV + c;
177
                                ckb = UBX_CLASS_NAV + cka;
178
                        }
179
                        break;
180
 
181
                case UBXSTATE_LEN1: // 1st message length byte
182
                        msglen = c;
183
                        cka += c;
184
                        ckb += cka;
185
                        ubxstate = UBXSTATE_LEN2;
186
                        break;
187
 
188
                case UBXSTATE_LEN2: // 2nd message length byte
189
                        msglen += ((uint16_t)c)<<8;
190
                        cka += c;
191
                        ckb += cka;
192
                        // if the old data are not processed so far then break parsing now
193
                        // to avoid writing new data in ISR during reading by another function
194
                        if ( *ubxSp == VALID ) ubxstate = UBXSTATE_IDLE;
195
                        else // data invalid or allready processd
196
                        {
197
                                *ubxSp = INVALID;
198
                                ubxstate = UBXSTATE_DATA;
199
                        }
200
                        break;
201
 
202
                case UBXSTATE_DATA:
203
                        if (ubxP < ubxEp) *ubxP++ = c; // copy curent data byte if any space is left
204
                        cka += c;
205
                        ckb += cka;
206
                        if (--msglen == 0)      ubxstate = UBXSTATE_CKA; // switch to next state if all data was read
207
                        break;
208
 
209
                case UBXSTATE_CKA:
210
                        if (c == cka) ubxstate = UBXSTATE_CKB;
722 killagreg 211
                        else
212
                        {
213
                                *ubxSp = INVALID;
214
                                ubxstate = UBXSTATE_IDLE;
215
                        }
684 killagreg 216
                        break;
217
 
218
                case UBXSTATE_CKB:
219
                        if (c == ckb)
220
                        {
722 killagreg 221
                                *ubxSp = VALID; // new data are valid
222
                                ROT_FLASH;
684 killagreg 223
                                UpdateGPSInfo(); //update GPS info respectively
224
                        }
722 killagreg 225
                        else
226
                        {       // if checksum not fit then set data invalid
227
                                *ubxSp = INVALID;
228
                        }
684 killagreg 229
                        ubxstate = UBXSTATE_IDLE; // ready to parse new data
230
                        break;
231
 
232
                default: // unknown ubx state
233
                        ubxstate = UBXSTATE_IDLE;
234
                        break;
235
        }
236
 
237
}
238