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

Commit 9159207

Browse files
Merge pull request #186 from ungureanuvladvictor/viterbi_decoder
Viterbi decoder
2 parents 0a1ac49 + b3685f4 commit 9159207

File tree

13 files changed

+855
-2
lines changed

13 files changed

+855
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ endif ()
7171
add_subdirectory(clapack-3.2.1-CMAKE)
7272
add_subdirectory(CBLAS)
7373
add_subdirectory(plover)
74+
add_subdirectory(libfec)
7475
add_subdirectory(src)
7576
add_subdirectory(docs)
7677
add_subdirectory(tests)

libfec/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Disable code coverage for this subdirectory
2+
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG}")
3+
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
4+
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
5+
6+
# Build libraries with PIC flag as they will be linked into shared objects
7+
if (NOT CMAKE_CROSSCOMPILING)
8+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
9+
endif ()
10+
11+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
12+
add_subdirectory(src)

libfec/LICENSE.txt

Lines changed: 504 additions & 0 deletions
Large diffs are not rendered by default.

libfec/include/fec.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* User include file for libfec
2+
* Copyright 2004, Phil Karn, KA9Q
3+
* May be used under the terms of the GNU Lesser General Public License (LGPL)
4+
*/
5+
6+
#ifndef _FEC_H_
7+
#define _FEC_H_
8+
9+
/* r=1/2 k=7 convolutional encoder polynomials
10+
* The NASA-DSN convention is to use V27POLYA inverted, then V27POLYB
11+
* The CCSDS/NASA-GSFC convention is to use V27POLYB, then V27POLYA inverted
12+
*/
13+
#define V27POLYA 0x4f
14+
#define V27POLYB 0x6d
15+
16+
typedef union {
17+
unsigned int w[64];
18+
} metric_t;
19+
20+
typedef union {
21+
unsigned int w[2];
22+
} decision_t;
23+
24+
union branchtab27 {
25+
unsigned char c[32];
26+
};
27+
28+
/* State info for instance of Viterbi decoder
29+
*/
30+
struct v27 {
31+
metric_t metrics1; /* path metric buffer 1 */
32+
metric_t metrics2; /* path metric buffer 2 */
33+
decision_t *dp; /* Pointer to current decision */
34+
metric_t *old_metrics,*new_metrics; /* Pointers to path metrics, swapped on every bit */
35+
decision_t *decisions; /* Beginning of decisions for block */
36+
};
37+
38+
void set_decisions_viterbi27(struct v27 *vp, decision_t *dec);
39+
void init_viterbi27(struct v27 *vp, int starting_state);
40+
void set_viterbi27_polynomial(int polys[2]);
41+
int update_viterbi27_blk(struct v27 *p, const unsigned char sym[], int npairs);
42+
int chainback_viterbi27(struct v27 *p, unsigned char *data, unsigned int nbits,
43+
unsigned int endstate);
44+
45+
static inline int parity(int x)
46+
{
47+
x ^= x >> 16;
48+
x ^= x >> 8;
49+
x ^= x >> 4;
50+
x &= 0xf;
51+
return (0x6996 >> x) & 1;
52+
}
53+
54+
#endif

libfec/src/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
if (NOT DEFINED BUILD_SHARED_LIBS)
2+
set(BUILD_SHARED_LIBS ON)
3+
endif (NOT DEFINED BUILD_SHARED_LIBS)
4+
5+
set(CMAKE_C_FLAGS "-Wmissing-prototypes ${CMAKE_C_FLAGS}")
6+
7+
file(GLOB libfec_HEADERS "${PROJECT_SOURCE_DIR}/libfec/include/*.h")
8+
9+
set(viterbi27.c)
10+
add_library(fec viterbi27.c)
11+
12+
install(TARGETS fec DESTINATION lib${LIB_SUFFIX})
13+
14+
install(FILES ${libfec_HEADERS} DESTINATION include/libswiftnav)

libfec/src/viterbi27.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/* K=7 r=1/2 Viterbi decoder in portable C
2+
* Copyright Feb 2004, Phil Karn, KA9Q
3+
* May be used under the terms of the GNU Lesser General Public License (LGPL)
4+
*/
5+
6+
#include <stdlib.h>
7+
#include "fec.h"
8+
9+
static union branchtab27 Branchtab27[2] __attribute__ ((aligned(16)));
10+
11+
void set_viterbi27_polynomial(int polys[2])
12+
{
13+
int state;
14+
15+
for(state = 0; state < 32; state++) {
16+
Branchtab27[0].c[state] = (polys[0] < 0) ^ parity((2*state) & abs(polys[0])) ? 255 : 0;
17+
Branchtab27[1].c[state] = (polys[1] < 0) ^ parity((2*state) & abs(polys[1])) ? 255 : 0;
18+
}
19+
}
20+
21+
/* Create a new instance of a Viterbi decoder */
22+
void init_viterbi27(struct v27 *vp, int starting_state)
23+
{
24+
int i;
25+
int polys[2] = { V27POLYA, V27POLYB };
26+
27+
set_viterbi27_polynomial(polys);
28+
29+
for(i = 0; i < 64; i++)
30+
vp->metrics1.w[i] = 63;
31+
32+
vp->old_metrics = &vp->metrics1;
33+
vp->new_metrics = &vp->metrics2;
34+
vp->dp = vp->decisions;
35+
vp->old_metrics->w[starting_state & 63] = 0; /* Bias known start state */
36+
}
37+
38+
/* Viterbi chainback */
39+
int chainback_viterbi27(
40+
struct v27 *vp,
41+
unsigned char *data, /* Decoded output data */
42+
unsigned int nbits, /* Number of data bits */
43+
unsigned int endstate) /* Terminal encoder state */
44+
{
45+
decision_t *d;
46+
47+
if(vp == NULL)
48+
return -1;
49+
50+
d = vp->decisions;
51+
/* Make room beyond the end of the encoder register so we can
52+
* accumulate a full byte of decoded data
53+
*/
54+
endstate %= 64;
55+
endstate <<= 2;
56+
57+
/* The store into data[] only needs to be done every 8 bits.
58+
* But this avoids a conditional branch, and the writes will
59+
* combine in the cache anyway
60+
*/
61+
d += 6; /* Look past tail */
62+
while(nbits-- != 0) {
63+
int k;
64+
65+
k = (d[nbits].w[(endstate>>2)/32] >> ((endstate>>2)%32)) & 1;
66+
data[nbits>>3] = endstate = (endstate >> 1) | (k << 7);
67+
}
68+
69+
return 0;
70+
}
71+
72+
/* C-language butterfly */
73+
#define BFLY(i) {\
74+
unsigned int metric,m0,m1,decision;\
75+
metric = (Branchtab27[0].c[i] ^ sym0) + (Branchtab27[1].c[i] ^ sym1);\
76+
m0 = vp->old_metrics->w[i] + metric;\
77+
m1 = vp->old_metrics->w[i+32] + (510 - metric);\
78+
decision = (signed int)(m0-m1) > 0;\
79+
vp->new_metrics->w[2*i] = decision ? m1 : m0;\
80+
d->w[i/16] |= decision << ((2*i)&31);\
81+
m0 -= (metric+metric-510);\
82+
m1 += (metric+metric-510);\
83+
decision = (signed int)(m0-m1) > 0;\
84+
vp->new_metrics->w[2*i+1] = decision ? m1 : m0;\
85+
d->w[i/16] |= decision << ((2*i+1)&31);\
86+
}
87+
88+
/* Update decoder with a block of demodulated symbols
89+
* Note that nbits is the number of decoded data bits, not the number
90+
* of symbols!
91+
*/
92+
int update_viterbi27_blk(struct v27 *vp, const unsigned char *syms, int nbits)
93+
{
94+
void *tmp;
95+
decision_t *d;
96+
97+
if(vp == NULL)
98+
return -1;
99+
100+
d = (decision_t *)vp->dp;
101+
102+
while(nbits--) {
103+
unsigned char sym0,sym1;
104+
105+
d->w[0] = d->w[1] = 0;
106+
sym0 = *syms++;
107+
sym1 = *syms++;
108+
109+
BFLY(0);
110+
BFLY(1);
111+
BFLY(2);
112+
BFLY(3);
113+
BFLY(4);
114+
BFLY(5);
115+
BFLY(6);
116+
BFLY(7);
117+
BFLY(8);
118+
BFLY(9);
119+
BFLY(10);
120+
BFLY(11);
121+
BFLY(12);
122+
BFLY(13);
123+
BFLY(14);
124+
BFLY(15);
125+
BFLY(16);
126+
BFLY(17);
127+
BFLY(18);
128+
BFLY(19);
129+
BFLY(20);
130+
BFLY(21);
131+
BFLY(22);
132+
BFLY(23);
133+
BFLY(24);
134+
BFLY(25);
135+
BFLY(26);
136+
BFLY(27);
137+
BFLY(28);
138+
BFLY(29);
139+
BFLY(30);
140+
BFLY(31);
141+
d++;
142+
143+
/* Swap pointers to old and new metrics */
144+
tmp = vp->old_metrics;
145+
vp->old_metrics = vp->new_metrics;
146+
vp->new_metrics = tmp;
147+
}
148+
149+
vp->dp = d;
150+
return 0;
151+
}
152+
153+
154+
void set_decisions_viterbi27(struct v27 *vp, decision_t *dec)
155+
{
156+
vp->decisions = dec;
157+
}

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ add_library(swiftnav-static STATIC ${libswiftnav_SRCS})
4848
add_dependencies(swiftnav-static generate)
4949
target_link_libraries(swiftnav-static cblas)
5050
target_link_libraries(swiftnav-static lapack)
51+
target_link_libraries(swiftnav-static fec)
5152
install(TARGETS swiftnav-static DESTINATION lib${LIB_SUFFIX})
5253

5354
if(BUILD_SHARED_LIBS)
5455
add_library(swiftnav SHARED ${libswiftnav_SRCS})
5556
add_dependencies(swiftnav generate)
5657
target_link_libraries(swiftnav cblas)
5758
target_link_libraries(swiftnav lapack)
59+
target_link_libraries(swiftnav fec)
5860
install(TARGETS swiftnav DESTINATION lib${LIB_SUFFIX})
5961
else(BUILD_SHARED_LIBS)
6062
message(STATUS "Not building shared libraries")

tests/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ else (CMAKE_CROSSCOMPILING)
1111
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
1212

1313
include_directories(${CHECK_INCLUDE_DIRS})
14-
set(TEST_LIBS ${TEST_LIBS} ${CHECK_LIBRARIES} pthread swiftnav lapack cblas m)
15-
14+
set(TEST_LIBS ${TEST_LIBS} ${CHECK_LIBRARIES} pthread swiftnav lapack cblas m fec)
1615
# Check needs to be linked against Librt on Linux
1716
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
1817
set(TEST_LIBS ${TEST_LIBS} rt)
1918
endif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
2019

2120
include_directories("${PROJECT_SOURCE_DIR}/include/libswiftnav")
2221
include_directories("${PROJECT_SOURCE_DIR}/src")
22+
include_directories("${PROJECT_SOURCE_DIR}/libfec/include")
2323

2424
add_executable(test_libswiftnav
2525
check_main.c
@@ -41,6 +41,7 @@ else (CMAKE_CROSSCOMPILING)
4141
check_filter_utils.c
4242
check_ephemeris.c
4343
check_set.c
44+
check_viterbi.c
4445
check_gpstime.c
4546
)
4647

@@ -50,6 +51,8 @@ else (CMAKE_CROSSCOMPILING)
5051
COMMENT "Running unit tests"
5152
COMMAND test_libswiftnav
5253
)
54+
file(COPY data/waas_check.bin DESTINATION ${CMAKE_BINARY_DIR}/tests)
55+
file(COPY data/waas_data.bin DESTINATION ${CMAKE_BINARY_DIR}/tests)
5356

5457
endif (NOT CHECK_FOUND)
5558
endif (CMAKE_CROSSCOMPILING)

tests/check_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int main(void)
2626
srunner_add_suite(sr, filter_utils_suite());
2727
srunner_add_suite(sr, ephemeris_suite());
2828
srunner_add_suite(sr, set_suite());
29+
srunner_add_suite(sr, viterbi_suite());
2930
srunner_add_suite(sr, gpstime_test_suite());
3031

3132
srunner_set_fork_status(sr, CK_NOFORK);

tests/check_suites.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Suite* ambiguity_test_suite(void);
1717
Suite* filter_utils_suite(void);
1818
Suite* ephemeris_suite(void);
1919
Suite* set_suite(void);
20+
Suite* viterbi_suite(void);
2021
Suite* gpstime_test_suite(void);
2122

2223
#endif /* CHECK_SUITES_H */

0 commit comments

Comments
 (0)