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