Skip to content
This repository was archived by the owner on Apr 13, 2021. It is now read-only.

Commit 5ae607f

Browse files
author
Roman Gezikov
committed
Merge pull request #337 from dt-exafore/i123-glo-decoder-error-corrections
I123 glo decoder error detector
2 parents a20edb4 + 80d90e7 commit 5ae607f

File tree

3 files changed

+238
-21
lines changed

3 files changed

+238
-21
lines changed

include/libswiftnav/nav_msg_glo.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
/** Length of GLO time mark */
2424
#define GLO_TM_LEN 30
2525

26+
/** Length of GLO navigation string */
27+
#define GLO_STR_LEN 85
28+
2629
/* States of receiver GLO bitstream */
2730
typedef enum {
2831
INVALID = -1,
@@ -43,11 +46,14 @@ typedef struct {
4346
glo_receive_machine state; /**< current state of receiver */
4447
u8 meander_bits_cnt:2; /**< counter for line code bits, MAX is 2 */
4548
u8 manchester:2; /**< 2 bits line code received */
49+
u8 decode_done:1; /**< decode done flag */
50+
u8 inverted:1; /**< incoming data is inverted */
4651
} nav_msg_glo_t;
4752

4853
void nav_msg_init_glo(nav_msg_glo_t *n);
4954
s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e);
50-
u32 extract_word_glo(const nav_msg_glo_t *n, u16 bit_index, u8 n_bits);
5155
s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val);
56+
s8 error_detection_glo(const nav_msg_glo_t *n);
57+
double nav_msg_get_tow_glo(const nav_msg_glo_t *n);
5258

5359
#endif /* LIBSWIFTNAV_NAV_MSG_GLO_H */

src/nav_msg_glo.c

Lines changed: 130 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <math.h>
1616
#include <libswiftnav/nav_msg_glo.h>
1717
#include <libswiftnav/time.h>
18+
#include <libswiftnav/logging.h>
19+
#include <libswiftnav/bits.h>
1820

1921
/* Word Ft (accuracy of measurements), refer to GLO ICD, Table 4.4 */
2022
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,
2325
/* Word P1 (Time interval between adjacent values of tb, minutes), refer Table 4.3 */
2426
const u8 p1[] = { 0, 30, 45, 60 }; /* min */
2527

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+
2642
/** Initialize the necessary parts of the nav message state structure.
2743
* \param n Pointer to GLO nav message structure to be initialized
2844
*/
@@ -33,17 +49,97 @@ void nav_msg_init_glo(nav_msg_glo_t *n)
3349
n->state = SYNC_TM;
3450
}
3551

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+
36125
/** Extract a word of n_bits length (n_bits <= 32) at position bit_index into
37126
* the subframe. Refer to bit index to Table 4.6 and 4.11 in GLO ICD 5.1 (pg. 34)
38127
* \param n pointer to GLO nav message structure to be parsed
39128
* \param bit_index number of bit the extract process start with. Range [1..85]
40129
* \param n_bits how many bits should be extracted [1..32]
41130
* \return word extracted from navigation string
42131
*/
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)
44133
{
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+
}
47143

48144
/* Extract a word of n_bits length (n_bits <= 32) at position bit_index into
49145
* the GLO string.*/
@@ -83,12 +179,17 @@ s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
83179
n->string_bits[0] <<= 1; /* use one word of buffer for that purpose */
84180
n->string_bits[0] |= bit_val;
85181
/* 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)) {
87184
/* time mark found, next time start collecting data bits */
88185
n->meander_bits_cnt = 0;
89186
n->manchester = 0;
90187
n->state = GET_DATA_BIT;
91188
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;
92193
}
93194
break;
94195
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)
106207
n->string_bits[i] = tmp;
107208
}
108209
n->string_bits[0] <<= 1;
210+
211+
/* set type of meander depending on inversion */
212+
u8 meander = n->inverted ? 1 : 2;
109213
/* 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;
111215
n->current_head_bit_index++;
112216
n->meander_bits_cnt = 0;
113217
n->manchester = 0;
114218
/* did we received all bits of a string?
115219
* 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) {
117221
n->current_head_bit_index = 0;
118222
n->state = SYNC_TM;
119223
ret = 1;
@@ -138,7 +242,7 @@ s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
138242
s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
139243
{
140244
/* 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) {
142246
log_error("GLO dummy bit is not 0.");
143247
return -1;
144248
}
@@ -148,6 +252,7 @@ s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
148252
u8 sign;
149253
/* is the string we need? */
150254
if (n->next_string_id == m) {
255+
n->decode_done = 0;
151256
switch (m) {
152257
case 1: /* string 1 */
153258
/* extract x */
@@ -238,24 +343,38 @@ s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
238343
/* extract N4 */
239344
n->n4 = (u8) extract_word_glo(n, 32, 5);
240345

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 */
242348
break;
243349
default:
244350
break;
245351
}
246352
}
247353
/* all needed strings decoded?
248354
* fill ephemeris structure if we was not able to do it before*/
249-
if (n->next_string_id == 0) {
355+
if (n->decode_done) {
250356
e->sid.code = CODE_GLO_L1CA;
251357
/* convert GLO TOE to GPS TOE */
252358
e->toe = glo_time2gps_time(n->nt, n->n4, n->hrs, n->min, n->sec);
253359
e->healthy ^= 1; /* invert healthy bit */
254360
e->valid = e->healthy; //NOTE: probably Valid needs to be defined by other way
255-
n->next_string_id = 1; /* start from string 1 */
256361
return 1;
257362
}
258363

259-
260364
return 0;
261365
}
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

Comments
 (0)