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

Commit a20edb4

Browse files
author
Roman Gezikov
committed
Merge pull request #329 from dt-exafore/i123-glo-decoder-test-data
Add test data for GLO decoder
2 parents d269099 + bbec7d8 commit a20edb4

File tree

12 files changed

+645
-2
lines changed

12 files changed

+645
-2
lines changed

include/libswiftnav/nav_msg_glo.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (C) 2016 Swift Navigation Inc.
3+
* Contact: Dmitry Tatarinov <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#ifndef LIBSWIFTNAV_NAV_MSG_GLO_H
14+
#define LIBSWIFTNAV_NAV_MSG_GLO_H
15+
16+
#include <libswiftnav/common.h>
17+
#include <libswiftnav/ephemeris.h>
18+
19+
#define NAV_MSG_GLO_STRING_BITS_LEN 3 /* Buffer 96 nav bits. */
20+
21+
/** Time mark in GLO nav string, GLO ICD, pg. 16 */
22+
#define GLO_TM (0x3E375096)
23+
/** Length of GLO time mark */
24+
#define GLO_TM_LEN 30
25+
26+
/* States of receiver GLO bitstream */
27+
typedef enum {
28+
INVALID = -1,
29+
SYNC_TM, /**< Time mark search */
30+
GET_DATA_BIT /**< Data bit receive */
31+
} glo_receive_machine;
32+
33+
/* The structure is used for GLO receive and decode bitstream */
34+
typedef struct {
35+
u32 string_bits[NAV_MSG_GLO_STRING_BITS_LEN]; /**< buffer for one GLO string */
36+
u16 current_head_bit_index; /**< how many bits written into GLO string buffer*/
37+
u16 nt; /**< tmp container for TOE calculation */
38+
u8 next_string_id; /**< what is the next string we need for parsing */
39+
u8 n4; /**< tmp container for TOE calculation */
40+
u8 hrs; /**< tmp container for TOE calculation */
41+
u8 min; /**< tmp container for TOE calculation */
42+
u8 sec; /**< tmp container for TOE calculation */
43+
glo_receive_machine state; /**< current state of receiver */
44+
u8 meander_bits_cnt:2; /**< counter for line code bits, MAX is 2 */
45+
u8 manchester:2; /**< 2 bits line code received */
46+
} nav_msg_glo_t;
47+
48+
void nav_msg_init_glo(nav_msg_glo_t *n);
49+
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);
51+
s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val);
52+
53+
#endif /* LIBSWIFTNAV_NAV_MSG_GLO_H */

include/libswiftnav/time.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,6 @@ static inline bool is_leap_year(s32 year)
100100
return ((year%4==0) && (year%100!=0)) || (year%400==0);
101101
}
102102

103-
gps_time_t glo_time2gps_time(u16 nt, u8 n4, s8 h, s8 m, s8 s);
103+
gps_time_t glo_time2gps_time(u16 nt, u8 n4, u8 h, u8 m, u8 s);
104104

105105
#endif /* LIBSWIFTNAV_TIME_H */

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ set(libswiftnav_SRCS
4646
ionosphere.c
4747
bit_sync.c
4848
cnav_msg.c
49+
nav_msg_glo.c
4950
${plover_SRCS}
5051

5152
CACHE INTERNAL ""

src/nav_msg_glo.c

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
/*
2+
* Copyright (C) 2016 Swift Navigation Inc.
3+
* Contact: Dmitry Tatarinov <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
#include <assert.h>
13+
#include <string.h>
14+
#include <stdio.h>
15+
#include <math.h>
16+
#include <libswiftnav/nav_msg_glo.h>
17+
#include <libswiftnav/time.h>
18+
19+
/* Word Ft (accuracy of measurements), refer to GLO ICD, Table 4.4 */
20+
const float f_t[] = { 1.0f, 2.0f, 2.5f, 4.0f, 5.0f, 7.0f, 10.0f, 12.0f, 14.0f,
21+
16.0f, 32.0f, 64.0f, 128.0f, 256.0f, 512.0f, -1.0f };
22+
23+
/* Word P1 (Time interval between adjacent values of tb, minutes), refer Table 4.3 */
24+
const u8 p1[] = { 0, 30, 45, 60 }; /* min */
25+
26+
/** Initialize the necessary parts of the nav message state structure.
27+
* \param n Pointer to GLO nav message structure to be initialized
28+
*/
29+
void nav_msg_init_glo(nav_msg_glo_t *n)
30+
{
31+
memset(n, 0, sizeof(nav_msg_glo_t));
32+
n->next_string_id = 1; /* start parsing from string 1 */
33+
n->state = SYNC_TM;
34+
}
35+
36+
/** Extract a word of n_bits length (n_bits <= 32) at position bit_index into
37+
* the subframe. Refer to bit index to Table 4.6 and 4.11 in GLO ICD 5.1 (pg. 34)
38+
* \param n pointer to GLO nav message structure to be parsed
39+
* \param bit_index number of bit the extract process start with. Range [1..85]
40+
* \param n_bits how many bits should be extracted [1..32]
41+
* \return word extracted from navigation string
42+
*/
43+
u32 extract_word_glo(const nav_msg_glo_t *n, u16 bit_index, u8 n_bits)
44+
{
45+
assert(n_bits <= 32 && n_bits > 0);
46+
assert(bit_index <= 85 && bit_index > 0);
47+
48+
/* Extract a word of n_bits length (n_bits <= 32) at position bit_index into
49+
* the GLO string.*/
50+
bit_index--;
51+
u32 word = 0;
52+
u8 bix_hi = bit_index >> 5;
53+
u8 bix_lo = bit_index & 0x1F;
54+
if (bix_lo + n_bits <= 32) {
55+
word = n->string_bits[bix_hi] >> bix_lo;
56+
word &= (0xffffffff << (32 - n_bits)) >> (32 - n_bits);
57+
} else {
58+
u8 s = 32 - bix_lo;
59+
word = extract_word_glo(n, bit_index + 1, s)
60+
| extract_word_glo(n, bit_index + 1 + s, n_bits - s) << s;
61+
}
62+
63+
return word;
64+
}
65+
66+
/** Navigation message GLO decoding update.
67+
* Called once per nav bit interval (10 ms).
68+
* Performs the necessary steps to store the nav bits in buffer.
69+
*
70+
* \param n GLO Nav message decode state struct
71+
* \param bit_val State of the nav bit to process, 0 or 1
72+
*
73+
* \return 1 if Glo nav string ready for decoding,
74+
* -1 otherwise.
75+
*/
76+
s8 nav_msg_update_glo(nav_msg_glo_t *n, bool bit_val)
77+
{
78+
s8 ret = -1;
79+
80+
switch (n->state) {
81+
case SYNC_TM: /* try to find time mark */
82+
/* put incoming bit at the tail of the buffer */
83+
n->string_bits[0] <<= 1; /* use one word of buffer for that purpose */
84+
n->string_bits[0] |= bit_val;
85+
/* collected bits match time mark? if not stay at this state */
86+
if (extract_word_glo(n, 1, GLO_TM_LEN) == GLO_TM) {
87+
/* time mark found, next time start collecting data bits */
88+
n->meander_bits_cnt = 0;
89+
n->manchester = 0;
90+
n->state = GET_DATA_BIT;
91+
n->string_bits[0] = 0;
92+
}
93+
break;
94+
case GET_DATA_BIT: /* collect data bits of string */
95+
n->meander_bits_cnt++;
96+
n->manchester <<= 1;
97+
n->manchester |= bit_val; /* store incoming bit */
98+
/* did we take 2 bits of line code?
99+
* if yes, remove meander and store bit in buffer,
100+
* if no, stay at the state */
101+
if (n->meander_bits_cnt == 2) {
102+
/* shift whole buffer by 1 bit left */
103+
for (u8 i = NAV_MSG_GLO_STRING_BITS_LEN - 1; i > 0; i--) {
104+
u32 tmp = (n->string_bits[i] << 1)
105+
| ((n->string_bits[i - 1] & (1 << 31)) >> 31);
106+
n->string_bits[i] = tmp;
107+
}
108+
n->string_bits[0] <<= 1;
109+
/* store bit after meander removal to buffer */
110+
n->string_bits[0] |= (n->manchester ^ 2) & 1;
111+
n->current_head_bit_index++;
112+
n->meander_bits_cnt = 0;
113+
n->manchester = 0;
114+
/* did we received all bits of a string?
115+
* if yes, notify user and start searching time mark again*/
116+
if (n->current_head_bit_index == 85) {
117+
n->current_head_bit_index = 0;
118+
n->state = SYNC_TM;
119+
ret = 1;
120+
}
121+
}
122+
break;
123+
default:
124+
nav_msg_init_glo(n); //TODO: probably not needed to initialize next_string_id
125+
break;
126+
}
127+
return ret;
128+
}
129+
130+
/** The function decodes a GLO navigation string.
131+
* Assume we receive signal from GLONASS-M
132+
* \param n Pointer to nav_msg_glo_t structure which contains GLO string
133+
* \param e Pointer to Ephemeris to store
134+
* \return 0 - decode not completed,
135+
* 1 -- decode completed, all ephemeris data stored
136+
* <0 -- in case of an error.
137+
*/
138+
s8 process_string_glo(nav_msg_glo_t *n, ephemeris_t *e)
139+
{
140+
/* Extract and check dummy bit from GLO string, bit 85 in GLO string */
141+
if (extract_word_glo(n, 85, 1) != 0) {
142+
log_error("GLO dummy bit is not 0.");
143+
return -1;
144+
}
145+
/* Extract string number */
146+
u32 m = extract_word_glo(n, 81, 4);
147+
u32 ret;
148+
u8 sign;
149+
/* is the string we need? */
150+
if (n->next_string_id == m) {
151+
switch (m) {
152+
case 1: /* string 1 */
153+
/* extract x */
154+
ret = extract_word_glo(n, 9, 26);
155+
sign = extract_word_glo(n, 9 + 26, 1);
156+
e->glo.pos[0] = sign ?
157+
-1.0 * ret * pow(2, -11) * 1000.0 : ret * pow(2, -11) * 1000.0;
158+
/* extract Vx */
159+
ret = extract_word_glo(n, 41, 23);
160+
sign = extract_word_glo(n, 41 + 23, 1);
161+
e->glo.vel[0] = sign ?
162+
-1.0 * ret * pow(2, -20) * 1000.0 : ret * pow(2, -20) * 1000.0;
163+
/* extract Ax */
164+
ret = extract_word_glo(n, 36, 4);
165+
sign = extract_word_glo(n, 36 + 4, 1);
166+
e->glo.acc[0] = sign ?
167+
-1.0 * ret * pow(2, -30) * 1000.0 : ret * pow(2, -30) * 1000.0;
168+
/* extract tk */
169+
n->hrs = (u8) extract_word_glo(n, 65, 5);
170+
n->min = (u8) extract_word_glo(n, 70, 6);
171+
n->sec = (u8) extract_word_glo(n, 76, 1);
172+
173+
n->next_string_id = 2;
174+
break;
175+
case 2: /* string 2 */
176+
/* extract y */
177+
ret = extract_word_glo(n, 9, 26);
178+
sign = extract_word_glo(n, 9 + 26, 1);
179+
e->glo.pos[1] = sign ?
180+
-1.0 * ret * pow(2, -11) * 1000.0 : ret * pow(2, -11) * 1000.0;
181+
/* extract Vy */
182+
ret = extract_word_glo(n, 41, 23);
183+
sign = extract_word_glo(n, 41 + 23, 1);
184+
e->glo.vel[1] = sign ?
185+
-1.0 * ret * pow(2, -20) * 1000.0 : ret * pow(2, -20) * 1000.0;
186+
/* extract Ay */
187+
ret = extract_word_glo(n, 36, 4);
188+
sign = extract_word_glo(n, 36 + 4, 1);
189+
e->glo.acc[1] = sign ?
190+
-1.0 * ret * pow(2, -30) * 1000.0 : ret * pow(2, -30) * 1000.0;
191+
/* extract MSB of B (if the bit is clear the SV is OK ) */
192+
e->healthy = extract_word_glo(n, 80, 1);
193+
/* extract P1 */
194+
e->fit_interval = p1[extract_word_glo(n, 77, 2)];
195+
196+
n->next_string_id = 3;
197+
break;
198+
case 3: /* string 3 */
199+
/* extract z */
200+
ret = extract_word_glo(n, 9, 26);
201+
sign = extract_word_glo(n, 9 + 26, 1);
202+
e->glo.pos[2] = sign ?
203+
-1.0 * ret * pow(2, -11) * 1000.0 : ret * pow(2, -11) * 1000.0;
204+
/* extract Vz */
205+
ret = extract_word_glo(n, 41, 23);
206+
sign = extract_word_glo(n, 41 + 23, 1);
207+
e->glo.vel[2] = sign ?
208+
-1.0 * ret * pow(2, -20) * 1000.0 : ret * pow(2, -20) * 1000.0;
209+
/* extract Az */
210+
ret = extract_word_glo(n, 36, 4);
211+
sign = extract_word_glo(n, 36 + 4, 1);
212+
e->glo.acc[2] = sign ?
213+
-1.0 * ret * pow(2, -30) * 1000.0 : ret * pow(2, -30) * 1000.0;
214+
/* extract gamma */
215+
ret = extract_word_glo(n, 69, 10);
216+
sign = extract_word_glo(n, 69 + 10, 1);
217+
e->glo.gamma = sign ? -1.0 * ret * pow(2, -40) : ret * pow(2, -40);
218+
/* extract l, if the it is clear the SV is OK, so OR it with B */
219+
e->healthy |= extract_word_glo(n, 65, 1);
220+
221+
n->next_string_id = 4;
222+
break;
223+
case 4: /* string 4 */
224+
/* extract tau */
225+
ret = extract_word_glo(n, 59, 21);
226+
sign = extract_word_glo(n, 59 + 21, 1);
227+
e->glo.tau = sign ? -1.0 * ret * pow(2, -30) : ret * pow(2, -30);
228+
/* extract n */
229+
e->sid.sat = extract_word_glo(n, 11, 5);
230+
/* extract Ft (URA) */
231+
e->ura = f_t[extract_word_glo(n, 30, 4)];
232+
/*extract Nt*/
233+
n->nt = (u16) extract_word_glo(n, 16, 11);
234+
235+
n->next_string_id = 5;
236+
break;
237+
case 5: /* string 5 */
238+
/* extract N4 */
239+
n->n4 = (u8) extract_word_glo(n, 32, 5);
240+
241+
n->next_string_id = 0; /* all string parsed */
242+
break;
243+
default:
244+
break;
245+
}
246+
}
247+
/* all needed strings decoded?
248+
* fill ephemeris structure if we was not able to do it before*/
249+
if (n->next_string_id == 0) {
250+
e->sid.code = CODE_GLO_L1CA;
251+
/* convert GLO TOE to GPS TOE */
252+
e->toe = glo_time2gps_time(n->nt, n->n4, n->hrs, n->min, n->sec);
253+
e->healthy ^= 1; /* invert healthy bit */
254+
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+
return 1;
257+
}
258+
259+
260+
return 0;
261+
}

src/time.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ u16 gps_adjust_week_cycle(u16 wn_raw, u16 wn_ref)
139139
* |return converted gps time
140140
*/
141141

142-
gps_time_t glo_time2gps_time(u16 nt, u8 n4, s8 h, s8 m, s8 s)
142+
gps_time_t glo_time2gps_time(u16 nt, u8 n4, u8 h, u8 m, u8 s)
143143
{
144144
u8 j = 0;
145145
u16 day_of_year = 0;

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ else (CMAKE_CROSSCOMPILING)
4848
check_signal.c
4949
check_track.c
5050
check_cnav.c
51+
check_glo_decoder.c
5152
)
5253

5354
target_link_libraries(test_libswiftnav ${TEST_LIBS})

0 commit comments

Comments
 (0)