00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <math.h>
00014
00015 #include "bits.h"
00016 #include "edc.h"
00017 #include "rtcm3.h"
00018
00019 #define RTCM3_PREAMBLE 0xD3
00020 #define PRUNIT_GPS 299792.458
00022 #define CLIGHT 299792458.0
00023 #define FREQ1 1.57542e9
00024 #define LAMBDA1 (CLIGHT / FREQ1)
00025
00046 s16 rtcm3_check_frame(u8 *buff)
00047 {
00048
00049 u8 preamble = getbitu(buff, 0, 8);
00050 if (preamble != RTCM3_PREAMBLE)
00051 return -1;
00052
00053 s16 len = getbitu(buff, 14, 10);
00054
00055
00056 u32 crc_calc = crc24q(buff, len + 3, 0);
00057
00058
00059 u32 crc_frame = getbitu(buff, (len+3)*8, 24);
00060
00061 if (crc_calc != crc_frame)
00062 return -2;
00063
00064 return len;
00065 }
00066
00084 s8 rtcm3_write_frame(u16 len, u8 *buff)
00085 {
00086 if (len > 1023)
00087 return -1;
00088
00089
00090 setbitu(buff, 0, 8, RTCM3_PREAMBLE);
00091 setbitu(buff, 8, 6, 0);
00092 setbitu(buff, 14, 10, len);
00093
00094
00095 u32 crc = crc24q(buff, len + 3, 0);
00096
00097
00098 setbitu(buff, (len+3)*8, 24, crc);
00099
00100 return 0;
00101 }
00102
00147 void rtcm3_write_header(u8 *buff, u16 type, u16 id, gps_time_t t,
00148 u8 sync, u8 n_sat, u8 div_free, u8 smooth)
00149 {
00150 setbitu(buff, 0, 12, type);
00151 setbitu(buff, 12, 12, id);
00152 setbitu(buff, 24, 30, round(t.tow*1e3));
00153 setbitu(buff, 54, 1, sync);
00154 setbitu(buff, 55, 5, n_sat);
00155 setbitu(buff, 60, 1, div_free);
00156 setbitu(buff, 61, 3, smooth);
00157 }
00158
00177 void rtcm3_read_header(u8 *buff, u16 *type, u16 *id, double *tow,
00178 u8 *sync, u8 *n_sat, u8 *div_free, u8 *smooth)
00179 {
00180 *type = getbitu(buff, 0, 12);
00181 *id = getbitu(buff, 12, 12);
00182 *tow = getbitu(buff, 24, 30) / 1e3;
00183 *sync = getbitu(buff, 54, 1);
00184 *n_sat = getbitu(buff, 55, 5);
00185 *div_free = getbitu(buff, 60, 1);
00186 *smooth = getbitu(buff, 61, 3);
00187 }
00188
00195 static u8 to_lock_ind(u32 time)
00196 {
00197 if (time < 24)
00198 return time;
00199 if (time < 72)
00200 return (time + 24) / 2;
00201 if (time < 168)
00202 return (time + 120) / 4;
00203 if (time < 360)
00204 return (time + 408) / 8;
00205 if (time < 744)
00206 return (time + 1176) / 16;
00207 if (time < 937)
00208 return (time + 3096) / 32;
00209 return 127;
00210 }
00211
00218 static u32 from_lock_ind(u8 lock)
00219 {
00220 if (lock < 24)
00221 return lock;
00222 if (lock < 48)
00223 return 2*lock - 24;
00224 if (lock < 72)
00225 return 4*lock - 120;
00226 if (lock < 96)
00227 return 8*lock - 408;
00228 if (lock < 120)
00229 return 16*lock - 1176;
00230 if (lock < 127)
00231 return 32*lock - 3096;
00232 return 937;
00233 }
00234
00245 static void gen_obs_gps(navigation_measurement_t *nm,
00246 u8 *amb, u32 *pr, s32 *ppr, u8 *lock, u8 *cnr)
00247 {
00248
00249 *amb = (u8)(nm->raw_pseudorange / PRUNIT_GPS);
00250
00251
00252 *pr = (u32)lround((nm->raw_pseudorange - *amb * PRUNIT_GPS) / 0.02);
00253
00254
00255 double prc = *pr * 0.02 + *amb * PRUNIT_GPS;
00256
00257
00258 double cp_pr = nm->carrier_phase - prc / (CLIGHT / FREQ1);
00259
00260
00261
00262
00263
00264
00265
00266 if (fabs(cp_pr) > 1000) {
00267 nm->lock_time = 0;
00268 nm->carrier_phase -= (s32)cp_pr;
00269 cp_pr -= (s32)cp_pr;
00270 }
00271
00272
00273 *ppr = lround(cp_pr * (CLIGHT / FREQ1) / 0.0005);
00274
00275 if (lock)
00276 *lock = to_lock_ind(nm->lock_time);
00277
00278 if (cnr)
00279
00280
00281 *cnr = (u8)((10.0*log10(nm->snr) + 40.0) * 4.0);
00282 }
00283
00296 u16 rtcm3_encode_1002(u8 *buff, u16 id, gps_time_t t, u8 n_sat,
00297 navigation_measurement_t *nm, u8 sync)
00298 {
00299 rtcm3_write_header(buff, 1002, id, t, sync, n_sat, 0, 0);
00300
00301 u16 bit = 64;
00302
00303 u32 pr;
00304 s32 ppr;
00305 u8 amb, lock, cnr;
00306
00307 for (u8 i=0; i<n_sat; i++) {
00308 gen_obs_gps(&nm[i], &amb, &pr, &ppr, &lock, &cnr);
00309
00310 setbitu(buff, bit, 6, nm[i].prn + 1); bit += 6;
00311
00312 setbitu(buff, bit, 1, 0); bit += 1;
00313 setbitu(buff, bit, 24, pr); bit += 24;
00314 setbits(buff, bit, 20, ppr); bit += 20;
00315 setbitu(buff, bit, 7, lock); bit += 7;
00316 setbitu(buff, bit, 8, amb); bit += 8;
00317 setbitu(buff, bit, 8, cnr); bit += 8;
00318 }
00319
00320
00321 return (bit + 7) / 8;
00322 }
00323
00337 s8 rtcm3_decode_1002(u8 *buff, u16 *id, double *tow, u8 *n_sat,
00338 navigation_measurement_t *nm, u8 *sync)
00339 {
00340 u16 type;
00341 u8 div_free, smooth;
00342
00343 rtcm3_read_header(buff, &type, id, tow, sync, n_sat, &div_free, &smooth);
00344
00345 if (type != 1002)
00346
00347 return -1;
00348
00349
00350
00351 if (!nm)
00352
00353
00354 return 0;
00355
00356 u16 bit = 64;
00357 for (u8 i=0; i<*n_sat; i++) {
00358
00359 nm[i].prn = getbitu(buff, bit, 6) - 1; bit += 6;
00360
00361 u8 code = getbitu(buff, bit, 1); bit += 1;
00362
00363
00364 if (code == 1)
00365
00366 return -2;
00367
00368 u32 pr = getbitu(buff, bit,24); bit += 24;
00369 s32 ppr = getbits(buff, bit,20); bit += 20;
00370 u8 lock = getbitu(buff, bit, 7); bit += 7;
00371 u8 amb = getbitu(buff, bit, 8); bit += 8;
00372 u8 cnr = getbitu(buff, bit, 8); bit += 8;
00373
00374 nm[i].raw_pseudorange = 0.02*pr + PRUNIT_GPS*amb;
00375 nm[i].carrier_phase = (nm[i].raw_pseudorange + 0.0005*ppr) / (CLIGHT / FREQ1);
00376 nm[i].lock_time = from_lock_ind(lock);
00377 nm[i].snr = pow(10.0, ((cnr / 4.0) - 40.0) / 10.0);
00378 }
00379
00380 return 0;
00381 }
00382
00383