15
15
#include <math.h>
16
16
#include <libswiftnav/nav_msg_glo.h>
17
17
#include <libswiftnav/time.h>
18
+ #include <libswiftnav/logging.h>
19
+ #include <libswiftnav/bits.h>
18
20
19
21
/* Word Ft (accuracy of measurements), refer to GLO ICD, Table 4.4 */
20
22
const float f_t [] = { 1.0f , 2.0f , 2.5f , 4.0f , 5.0f , 7.0f , 10.0f , 12.0f , 14.0f ,
@@ -23,6 +25,20 @@ const float f_t[] = { 1.0f, 2.0f, 2.5f, 4.0f, 5.0f, 7.0f, 10.0f, 12.0f, 14.0f,
23
25
/* Word P1 (Time interval between adjacent values of tb, minutes), refer Table 4.3 */
24
26
const u8 p1 [] = { 0 , 30 , 45 , 60 }; /* min */
25
27
28
+ /* These bit masks (for data bits 9..85) correspond to table 4.13 of GLO ICD
29
+ * used in error correction algorithm */
30
+ const u32 e_masks [7 ][3 ] = {
31
+ { 0xaaad5b00 , 0x55555556 , 0xaaaab },
32
+ { 0x33366d00 , 0x9999999b , 0xccccd },
33
+ { 0xc3c78e00 , 0xe1e1e1e3 , 0x10f0f1 },
34
+ { 0xfc07f000 , 0xfe01fe03 , 0xff01 },
35
+ { 0xfff80000 , 0xfffe0003 , 0x1f0001 },
36
+ { 0 , 0xfffffffc , 1 },
37
+ { 0 , 0 , 0x1ffffe },
38
+ };
39
+
40
+ static u32 extract_word_glo (const nav_msg_glo_t * n , u16 bit_index , u8 n_bits );
41
+
26
42
/** Initialize the necessary parts of the nav message state structure.
27
43
* \param n Pointer to GLO nav message structure to be initialized
28
44
*/
@@ -33,17 +49,97 @@ void nav_msg_init_glo(nav_msg_glo_t *n)
33
49
n -> state = SYNC_TM ;
34
50
}
35
51
52
+ /** The function performs data verification and error correction
53
+ * in received GLO navigation string. Refer to GLO ICD, section 4.7
54
+ * \param n pointer to GLO nav message structure
55
+ * \return -1 -- received string is bad and should be dropped out,
56
+ * 0 -- received string is good
57
+ * >0 -- number of bit in n->string_bits to be corrected (inverted)
58
+ * range[9..85]*/
59
+ s8 error_detection_glo (const nav_msg_glo_t * n )
60
+ {
61
+ u8 c = 0 ;
62
+ u32 data1 , data2 , data3 ;
63
+ bool p0 , p1 , p2 , p3 , beta , c_sum ;
64
+ u8 bit_set = 0 ;
65
+ u8 k = 0 ;
66
+
67
+ /* calculate C1..7 */
68
+ for (u8 i = 0 ; i < 7 ; i ++ ) {
69
+ /* extract corresponding check bit of Hamming code */
70
+ beta = extract_word_glo (n , i + 1 , 1 );
71
+ /* extract data bits and apply mask */
72
+ data1 = extract_word_glo (n , 1 , 32 ) & e_masks [i ][0 ];
73
+ data2 = extract_word_glo (n , 33 , 32 ) & e_masks [i ][1 ];
74
+ data3 = extract_word_glo (n , 65 , 32 ) & e_masks [i ][2 ];
75
+ /* calculate parity for data[1..3] */
76
+ p1 = parity (data1 );
77
+ p2 = parity (data2 );
78
+ p3 = parity (data3 );
79
+ bool p = beta ^ p1 ^ p2 ^ p3 ;
80
+ /* calculate common parity and set according C bit */
81
+ c |= p << i ;
82
+ if (p ) {
83
+ bit_set ++ ; /* how many bits are set, used in error criteria */
84
+ k = i + 1 ; /* store number of most significant checksum not equal to 0,
85
+ used in error criteria */
86
+ }
87
+ }
88
+
89
+ /* calculate C sum */
90
+ data1 = extract_word_glo (n , 1 , 32 ) & 0xffffff00 ;
91
+ data2 = extract_word_glo (n , 33 , 32 );
92
+ data3 = extract_word_glo (n , 65 , 32 );
93
+ p1 = parity (data1 );
94
+ p2 = parity (data2 );
95
+ p3 = parity (data3 );
96
+ p0 = parity (extract_word_glo (n , 1 , 8 ));
97
+ c_sum = p0 ^ p1 ^ p2 ^ p3 ;
98
+
99
+ /* Now check C word to figure out is the string good, bad or
100
+ * correction is needed */
101
+ if ((!c_sum && !bit_set ) || (1 == bit_set && c_sum )) /* case a) from ICD */
102
+
103
+ return 0 ; /* The string is good */
104
+
105
+ if ((bit_set > 0 && !c_sum )
106
+ || (0 == bit_set && c_sum )) /* case c) from ICD */
107
+
108
+ return -1 ; /* multiple errors, bad string */
109
+
110
+ if (bit_set > 1 && c_sum ) { /* case b) from ICD */
111
+
112
+ u8 i_corr = (c & 0x7f ) + 8 - k ; /* define number of bit to be corrected */
113
+
114
+ if (i_corr > GLO_STR_LEN )
115
+ return -1 ; /* odd number of multiple errors, bad string */
116
+
117
+ return i_corr ; /* return the bit to be corrected */
118
+ }
119
+
120
+ /* should not be here */
121
+ log_error ("GLO error correction: unexpected case" );
122
+ return -1 ;
123
+ }
124
+
36
125
/** Extract a word of n_bits length (n_bits <= 32) at position bit_index into
37
126
* the subframe. Refer to bit index to Table 4.6 and 4.11 in GLO ICD 5.1 (pg. 34)
38
127
* \param n pointer to GLO nav message structure to be parsed
39
128
* \param bit_index number of bit the extract process start with. Range [1..85]
40
129
* \param n_bits how many bits should be extracted [1..32]
41
130
* \return word extracted from navigation string
42
131
*/
43
- u32 extract_word_glo (const nav_msg_glo_t * n , u16 bit_index , u8 n_bits )
132
+ static u32 extract_word_glo (const nav_msg_glo_t * n , u16 bit_index , u8 n_bits )
44
133
{
45
- assert (n_bits <= 32 && n_bits > 0 );
46
- assert (bit_index <= 85 && bit_index > 0 );
134
+ if (bit_index > GLO_STR_LEN || !bit_index ) {
135
+ log_error ("Incorrect bit index %d\n" , bit_index );
136
+ return 0 ;
137
+ }
138
+
139
+ if (n_bits > 32 || !n_bits ) {
140
+ log_error ("Incorrect number of bits to be extracted %d\n" , n_bits );
141
+ return 0 ;
142
+ }
47
143
48
144
/* Extract a word of n_bits length (n_bits <= 32) at position bit_index into
49
145
* the GLO string.*/
@@ -83,12 +179,17 @@ s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
83
179
n -> string_bits [0 ] <<= 1 ; /* use one word of buffer for that purpose */
84
180
n -> string_bits [0 ] |= bit_val ;
85
181
/* collected bits match time mark? if not stay at this state */
86
- if (extract_word_glo (n , 1 , GLO_TM_LEN ) == GLO_TM ) {
182
+ u32 tm = extract_word_glo (n , 1 , GLO_TM_LEN );
183
+ if (tm == GLO_TM || tm == (u32 )(~GLO_TM & 0x3fffffff )) {
87
184
/* time mark found, next time start collecting data bits */
88
185
n -> meander_bits_cnt = 0 ;
89
186
n -> manchester = 0 ;
90
187
n -> state = GET_DATA_BIT ;
91
188
n -> string_bits [0 ] = 0 ;
189
+ if (tm == GLO_TM )
190
+ n -> inverted = 0 ;
191
+ else if (tm == (u32 )(~GLO_TM & 0x3fffffff ))
192
+ n -> inverted = 1 ;
92
193
}
93
194
break ;
94
195
case GET_DATA_BIT : /* collect data bits of string */
@@ -106,14 +207,17 @@ s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
106
207
n -> string_bits [i ] = tmp ;
107
208
}
108
209
n -> string_bits [0 ] <<= 1 ;
210
+
211
+ /* set type of meander depending on inversion */
212
+ u8 meander = n -> inverted ? 1 : 2 ;
109
213
/* store bit after meander removal to buffer */
110
- n -> string_bits [0 ] |= (n -> manchester ^ 2 ) & 1 ;
214
+ n -> string_bits [0 ] |= (n -> manchester ^ meander ) & 1 ;
111
215
n -> current_head_bit_index ++ ;
112
216
n -> meander_bits_cnt = 0 ;
113
217
n -> manchester = 0 ;
114
218
/* did we received all bits of a string?
115
219
* if yes, notify user and start searching time mark again*/
116
- if (n -> current_head_bit_index == 85 ) {
220
+ if (n -> current_head_bit_index == GLO_STR_LEN ) {
117
221
n -> current_head_bit_index = 0 ;
118
222
n -> state = SYNC_TM ;
119
223
ret = 1 ;
@@ -138,7 +242,7 @@ s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
138
242
s8 process_string_glo (nav_msg_glo_t * n , ephemeris_t * e )
139
243
{
140
244
/* Extract and check dummy bit from GLO string, bit 85 in GLO string */
141
- if (extract_word_glo (n , 85 , 1 ) != 0 ) {
245
+ if (extract_word_glo (n , GLO_STR_LEN , 1 ) != 0 ) {
142
246
log_error ("GLO dummy bit is not 0." );
143
247
return -1 ;
144
248
}
@@ -148,6 +252,7 @@ s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
148
252
u8 sign ;
149
253
/* is the string we need? */
150
254
if (n -> next_string_id == m ) {
255
+ n -> decode_done = 0 ;
151
256
switch (m ) {
152
257
case 1 : /* string 1 */
153
258
/* extract x */
@@ -238,24 +343,38 @@ s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
238
343
/* extract N4 */
239
344
n -> n4 = (u8 ) extract_word_glo (n , 32 , 5 );
240
345
241
- n -> next_string_id = 0 ; /* all string parsed */
346
+ n -> next_string_id = 1 ; /* start decode from 1st string next time */
347
+ n -> decode_done = 1 ; /* all string parsed */
242
348
break ;
243
349
default :
244
350
break ;
245
351
}
246
352
}
247
353
/* all needed strings decoded?
248
354
* fill ephemeris structure if we was not able to do it before*/
249
- if (n -> next_string_id == 0 ) {
355
+ if (n -> decode_done ) {
250
356
e -> sid .code = CODE_GLO_L1CA ;
251
357
/* convert GLO TOE to GPS TOE */
252
358
e -> toe = glo_time2gps_time (n -> nt , n -> n4 , n -> hrs , n -> min , n -> sec );
253
359
e -> healthy ^= 1 ; /* invert healthy bit */
254
360
e -> valid = e -> healthy ; //NOTE: probably Valid needs to be defined by other way
255
- n -> next_string_id = 1 ; /* start from string 1 */
256
361
return 1 ;
257
362
}
258
363
259
-
260
364
return 0 ;
261
365
}
366
+
367
+ /** This function just a wrapper for glo_time2gps_time
368
+ * \param n pointer to GLO nav message
369
+ * \return time of GLO referenced to the end of the 5th GLO nav string presented as
370
+ * GPS time, -1 if ephemeris cannot be decoded */
371
+ double nav_msg_get_tow_glo (const nav_msg_glo_t * n )
372
+ {
373
+ /* + 10 sec for the end of 5th string */
374
+ if (!n -> decode_done )
375
+ return -1 ;
376
+ else {
377
+ gps_time_t t = glo_time2gps_time (n -> nt , n -> n4 , n -> hrs , n -> min , n -> sec + 10 );
378
+ return t .tow ;
379
+ }
380
+ }
0 commit comments