mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 04:00:34 +00:00
Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into common_solver
This commit is contained in:
commit
ab75381e33
@ -49,7 +49,7 @@ message(STATUS "Build type set to ${CMAKE_BUILD_TYPE}.")
|
||||
|
||||
set(VERSION_INFO_MAJOR_VERSION 0)
|
||||
set(VERSION_INFO_MINOR_VERSION 0)
|
||||
set(VERSION_INFO_MAINT_VERSION 9)
|
||||
set(VERSION_INFO_MAINT_VERSION 9.git)
|
||||
include(VolkVersion) #setup version info
|
||||
|
||||
|
||||
|
@ -57,7 +57,7 @@ This figure shows the role of some VOLK_GNSSSDR kernels in the context of a GNSS
|
||||
|
||||
If you use VOLK_GNSSSDR in your research and/or software, please cite the following paper:
|
||||
|
||||
* C. Fernández-Prades, J. Arribas, P. Closas, [*Accelerating GNSS Software Receivers*](https://zenodo.org/record/266493#.WJR8j7bhB89), in Proc. of the ION GNSS+ 2016 Conference, pp. 44-61, Portland, Oregon, Sept. 12-16, 2016.
|
||||
* C. Fernández-Prades, J. Arribas, P. Closas, [*Accelerating GNSS Software Receivers*](https://zenodo.org/record/266493), in Proc. of the ION GNSS+ 2016 Conference, pp. 44-61, Portland, Oregon, Sept. 12-16, 2016.
|
||||
|
||||
Citations are useful for the continued development and maintenance of the library.
|
||||
|
||||
|
@ -102,6 +102,9 @@ class volk_gnsssdr_modtool:
|
||||
os.makedirs(os.path.join(self.my_dict['destination'], 'volk_gnsssdr_' + self.my_dict['name'], 'kernels/volk_gnsssdr_' + self.my_dict['name']))
|
||||
|
||||
current_kernel_names = self.get_current_kernels();
|
||||
need_ifdef_updates = ["constant.h", "volk_complex.h", "volk_malloc.h", "volk_prefs.h",
|
||||
"volk_common.h", "volk_cpu.tmpl.h", "volk_config_fixed.tmpl.h",
|
||||
"volk_typedefs.h", "volk.tmpl.h"]
|
||||
|
||||
for root, dirnames, filenames in os.walk(self.my_dict['base']):
|
||||
for name in filenames:
|
||||
@ -111,8 +114,14 @@ class volk_gnsssdr_modtool:
|
||||
infile = os.path.join(root, name);
|
||||
instring = open(infile, 'r').read();
|
||||
outstring = re.sub(self.volk_gnsssdr, 'volk_gnsssdr_' + self.my_dict['name'], instring);
|
||||
if name in need_ifdef_updates:
|
||||
outstring = re.sub(self.volk_included, 'INCLUDED_VOLK_' + self.my_dict['name'].upper(), outstring)
|
||||
newname = re.sub(self.volk_gnsssdr, 'volk_gnsssdr_' + self.my_dict['name'], name);
|
||||
relpath = os.path.relpath(infile, self.my_dict['base']);
|
||||
if name == 'VolkConfig.cmake.in':
|
||||
outstring = re.sub("VOLK", 'VOLK_' + self.my_dict['name'].upper(), outstring)
|
||||
newname = "Volk%sConfig.cmake.in" % self.my_dict['name']
|
||||
|
||||
newrelpath = re.sub(self.volk_gnsssdr, 'volk_gnsssdr_' + self.my_dict['name'], relpath);
|
||||
dest = os.path.join(self.my_dict['destination'], 'volk_gnsssdr_' + self.my_dict['name'], os.path.dirname(newrelpath), newname);
|
||||
|
||||
|
@ -1,13 +1,32 @@
|
||||
/*
|
||||
/*!
|
||||
* \file bits.c
|
||||
* \author Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2013, 2016 Swift Navigation Inc.
|
||||
* Contact: Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
@ -33,11 +52,11 @@ static const u8 bitn[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
|
||||
*/
|
||||
u8 parity(u32 x)
|
||||
{
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
x &= 0xF;
|
||||
return (0x6996 >> x) & 1;
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
x &= 0xF;
|
||||
return (0x6996 >> x) & 1;
|
||||
}
|
||||
|
||||
|
||||
@ -53,11 +72,12 @@ u8 parity(u32 x)
|
||||
u32 getbitu(const u8 *buff, u32 pos, u8 len)
|
||||
{
|
||||
u32 bits = 0;
|
||||
|
||||
for (u32 i = pos; i < pos + len; i++) {
|
||||
bits = (bits << 1) +
|
||||
((buff[i/8] >> (7 - i%8)) & 1u);
|
||||
}
|
||||
u32 i=0;
|
||||
for (i = pos; i < pos + len; i++)
|
||||
{
|
||||
bits = (bits << 1) +
|
||||
((buff[i/8] >> (7 - i%8)) & 1u);
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
@ -95,17 +115,18 @@ s32 getbits(const u8 *buff, u32 pos, u8 len)
|
||||
*/
|
||||
void setbitu(u8 *buff, u32 pos, u32 len, u32 data)
|
||||
{
|
||||
u32 mask = 1u << (len - 1);
|
||||
u32 mask = 1u << (len - 1);
|
||||
|
||||
if (len <= 0 || 32 < len)
|
||||
return;
|
||||
|
||||
for (u32 i = pos; i < pos + len; i++, mask >>= 1) {
|
||||
if (data & mask)
|
||||
buff[i/8] |= 1u << (7 - i % 8);
|
||||
else
|
||||
buff[i/8] &= ~(1u << (7 - i % 8));
|
||||
}
|
||||
if (len <= 0 || 32 < len)
|
||||
return;
|
||||
u32 i = 0;
|
||||
for (i = pos; i < pos + len; i++, mask >>= 1)
|
||||
{
|
||||
if (data & mask)
|
||||
buff[i/8] |= 1u << (7 - i % 8);
|
||||
else
|
||||
buff[i/8] &= ~(1u << (7 - i % 8));
|
||||
}
|
||||
}
|
||||
|
||||
/** Set bit field in buffer from a signed integer.
|
||||
@ -119,7 +140,7 @@ void setbitu(u8 *buff, u32 pos, u32 len, u32 data)
|
||||
*/
|
||||
void setbits(u8 *buff, u32 pos, u32 len, s32 data)
|
||||
{
|
||||
setbitu(buff, pos, len, (u32)data);
|
||||
setbitu(buff, pos, len, (u32)data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,37 +155,43 @@ void setbits(u8 *buff, u32 pos, u32 len, s32 data)
|
||||
*/
|
||||
void bitshl(void *buf, u32 size, u32 shift)
|
||||
{
|
||||
if (shift > size * CHAR_BIT) {
|
||||
/* Quick check: if the shift is larger, than the buffer, zero the data */
|
||||
memset(buf, 0, size);
|
||||
return;
|
||||
}
|
||||
if (shift > size * CHAR_BIT)
|
||||
{
|
||||
/* Quick check: if the shift is larger, than the buffer, zero the data */
|
||||
memset(buf, 0, size);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *dst = buf; /* Destination byte. */
|
||||
const unsigned char *src = dst + shift / CHAR_BIT; /* First source byte,
|
||||
* possibly incomplete. */
|
||||
unsigned char *dst = buf; /* Destination byte. */
|
||||
const unsigned char *src = dst + shift / CHAR_BIT; /* First source byte, possibly incomplete. */
|
||||
|
||||
u32 copy_bits = size * CHAR_BIT - shift; /* Number of bits to move */
|
||||
u32 byte_shift = copy_bits % CHAR_BIT; /* Shift of data */
|
||||
u32 full_bytes = copy_bits / CHAR_BIT; /* Number of bytes to move */
|
||||
u32 copy_bits = size * CHAR_BIT - shift; /* Number of bits to move */
|
||||
u32 byte_shift = copy_bits % CHAR_BIT; /* Shift of data */
|
||||
u32 full_bytes = copy_bits / CHAR_BIT; /* Number of bytes to move */
|
||||
|
||||
if (0 == byte_shift) {
|
||||
/* When moving data in character boundaries, use built-in functions: move
|
||||
* data, and then zero the tail. */
|
||||
memmove(dst, src, full_bytes);
|
||||
memset(dst + full_bytes, 0, size - full_bytes);
|
||||
} else {
|
||||
/* Create an accumulator: it will hold a value of two consecutive bytes */
|
||||
u32 acc = *src++;
|
||||
for (u32 i = 0; i < full_bytes; ++i) {
|
||||
acc = (acc << CHAR_BIT) | *src++;
|
||||
*dst++ = acc >> byte_shift;
|
||||
}
|
||||
*dst++ = acc << CHAR_BIT >> byte_shift;
|
||||
if (full_bytes + 1 < size) {
|
||||
memset(dst, 0, size - full_bytes - 1);
|
||||
}
|
||||
}
|
||||
if (0 == byte_shift)
|
||||
{
|
||||
/* When moving data in character boundaries, use built-in functions: move
|
||||
* data, and then zero the tail. */
|
||||
memmove(dst, src, full_bytes);
|
||||
memset(dst + full_bytes, 0, size - full_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create an accumulator: it will hold a value of two consecutive bytes */
|
||||
u32 acc = *src++;
|
||||
u32 i = 0;
|
||||
for (i = 0; i < full_bytes; ++i)
|
||||
{
|
||||
acc = (acc << CHAR_BIT) | *src++;
|
||||
*dst++ = acc >> byte_shift;
|
||||
}
|
||||
*dst++ = acc << CHAR_BIT >> byte_shift;
|
||||
if (full_bytes + 1 < size)
|
||||
{
|
||||
memset(dst, 0, size - full_bytes - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,19 +213,21 @@ void bitshl(void *buf, u32 size, u32 shift)
|
||||
void bitcopy(void *dst, u32 dst_index, const void *src, u32 src_index,
|
||||
u32 count)
|
||||
{
|
||||
u32 limit1 = count / 32;
|
||||
u32 limit2 = count % 32;
|
||||
|
||||
for (u32 idx = 0; idx < limit1; ++idx) {
|
||||
u32 tmp = getbitu(src, src_index, 32);
|
||||
setbitu(dst, dst_index, 32, tmp);
|
||||
src_index += 32;
|
||||
dst_index += 32;
|
||||
}
|
||||
if (0 != limit2) {
|
||||
u32 tmp = getbitu(src, src_index, limit2);
|
||||
setbitu(dst, dst_index, limit2, tmp);
|
||||
}
|
||||
u32 limit1 = count / 32;
|
||||
u32 limit2 = count % 32;
|
||||
u32 idx = 0;
|
||||
for (idx = 0; idx < limit1; ++idx)
|
||||
{
|
||||
u32 tmp = getbitu(src, src_index, 32);
|
||||
setbitu(dst, dst_index, 32, tmp);
|
||||
src_index += 32;
|
||||
dst_index += 32;
|
||||
}
|
||||
if (0 != limit2)
|
||||
{
|
||||
u32 tmp = getbitu(src, src_index, limit2);
|
||||
setbitu(dst, dst_index, limit2, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,10 +240,11 @@ void bitcopy(void *dst, u32 dst_index, const void *src, u32 src_index,
|
||||
*/
|
||||
u8 count_bits_u64(u64 v, u8 bv)
|
||||
{
|
||||
u8 r = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 64 - r;
|
||||
u8 r = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 64 - r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -227,10 +257,11 @@ u8 count_bits_u64(u64 v, u8 bv)
|
||||
*/
|
||||
u8 count_bits_u32(u32 v, u8 bv)
|
||||
{
|
||||
u8 r = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 32 - r;
|
||||
u8 r = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 32 - r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,10 +274,11 @@ u8 count_bits_u32(u32 v, u8 bv)
|
||||
*/
|
||||
u8 count_bits_u16(u16 v, u8 bv)
|
||||
{
|
||||
u8 r = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 16 - r;
|
||||
u8 r = 0;
|
||||
int i = 0;
|
||||
for (i= 0; i < 4; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 16 - r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,10 +291,11 @@ u8 count_bits_u16(u16 v, u8 bv)
|
||||
*/
|
||||
u8 count_bits_u8(u8 v, u8 bv)
|
||||
{
|
||||
u8 r = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 8 - r;
|
||||
u8 r = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
r += bitn[(v >> (i*4)) & 0xf];
|
||||
return bv == 1 ? r : 8 - r;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1,13 +1,32 @@
|
||||
/*
|
||||
/*!
|
||||
* \file bits.h
|
||||
* \author Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2013, 2016 Swift Navigation Inc.
|
||||
* Contact: Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBSWIFTNAV_BITS_H
|
||||
|
@ -1,15 +1,36 @@
|
||||
/*
|
||||
/*!
|
||||
* \file cnav_msg.c
|
||||
* \author Valeri Atamaniouk <valeri@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2016 Swift Navigation Inc.
|
||||
* Contact: Valeri Atamaniouk <valeri@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "edc.h"
|
||||
#include "bits.h"
|
||||
#include "cnav_msg.h"
|
||||
@ -63,12 +84,13 @@
|
||||
*/
|
||||
static u32 _cnav_compute_crc(cnav_v27_part_t *part)
|
||||
{
|
||||
u32 crc = crc24q_bits(0, part->decoded, GPS_CNAV_MSG_DATA_LENGTH,
|
||||
part->invert);
|
||||
u32 crc = crc24q_bits(0, part->decoded, GPS_CNAV_MSG_DATA_LENGTH,
|
||||
part->invert);
|
||||
|
||||
return crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts CRC-24Q from a CNAV message buffer.
|
||||
* CRC-24Q value is the last 24 bits from 300 bits message buffer.
|
||||
@ -81,14 +103,16 @@ static u32 _cnav_compute_crc(cnav_v27_part_t *part)
|
||||
*/
|
||||
static u32 _cnav_extract_crc(const cnav_v27_part_t *part)
|
||||
{
|
||||
u32 crc = getbitu(part->decoded, GPS_CNAV_MSG_DATA_LENGTH,
|
||||
GPS_CNAV_MSG_CRC_LENGTH);
|
||||
if (part->invert) {
|
||||
crc ^= 0xFFFFFF;
|
||||
}
|
||||
return crc;
|
||||
u32 crc = getbitu(part->decoded, GPS_CNAV_MSG_DATA_LENGTH,
|
||||
GPS_CNAV_MSG_CRC_LENGTH);
|
||||
if (part->invert)
|
||||
{
|
||||
crc ^= 0xFFFFFF;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to rescan for preamble in the received buffer.
|
||||
* Occasionally there could be a false lock on message contents if it the
|
||||
@ -105,29 +129,35 @@ static u32 _cnav_extract_crc(const cnav_v27_part_t *part)
|
||||
*/
|
||||
static void _cnav_rescan_preamble(cnav_v27_part_t *part)
|
||||
{
|
||||
part->preamble_seen = false;
|
||||
part->preamble_seen = false;
|
||||
|
||||
if (part->n_decoded > GPS_CNAV_PREAMBLE_LENGTH + 1) {
|
||||
for (size_t i = 1, j = part->n_decoded - GPS_CNAV_PREAMBLE_LENGTH;
|
||||
i < j; ++i) {
|
||||
u32 c = getbitu(part->decoded, i, GPS_CNAV_PREAMBLE_LENGTH);
|
||||
if (GPS_CNAV_PREAMBLE1 == c || GPS_CNAV_PREAMBLE2 == c) {
|
||||
part->preamble_seen = true;
|
||||
part->invert = (GPS_CNAV_PREAMBLE2 == c);
|
||||
/* We shift the accumulated bits to the beginning of the buffer */
|
||||
bitshl(part->decoded, sizeof(part->decoded), i);
|
||||
part->n_decoded -= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!part->preamble_seen && part->n_decoded >= GPS_CNAV_PREAMBLE_LENGTH) {
|
||||
bitshl(part->decoded, sizeof(part->decoded),
|
||||
part->n_decoded - GPS_CNAV_PREAMBLE_LENGTH + 1);
|
||||
part->n_decoded = GPS_CNAV_PREAMBLE_LENGTH - 1;
|
||||
}
|
||||
if (part->n_decoded > GPS_CNAV_PREAMBLE_LENGTH + 1)
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
for (i = 1, j = part->n_decoded - GPS_CNAV_PREAMBLE_LENGTH; i < j; ++i)
|
||||
{
|
||||
u32 c = getbitu(part->decoded, i, GPS_CNAV_PREAMBLE_LENGTH);
|
||||
if (GPS_CNAV_PREAMBLE1 == c || GPS_CNAV_PREAMBLE2 == c)
|
||||
{
|
||||
part->preamble_seen = true;
|
||||
part->invert = (GPS_CNAV_PREAMBLE2 == c);
|
||||
/* We shift the accumulated bits to the beginning of the buffer */
|
||||
bitshl(part->decoded, sizeof(part->decoded), i);
|
||||
part->n_decoded -= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!part->preamble_seen && part->n_decoded >= GPS_CNAV_PREAMBLE_LENGTH)
|
||||
{
|
||||
bitshl(part->decoded, sizeof(part->decoded),
|
||||
part->n_decoded - GPS_CNAV_PREAMBLE_LENGTH + 1);
|
||||
part->n_decoded = GPS_CNAV_PREAMBLE_LENGTH - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Feed a symbol into Viterbi decoder instance.
|
||||
*
|
||||
@ -144,110 +174,126 @@ static void _cnav_rescan_preamble(cnav_v27_part_t *part)
|
||||
*/
|
||||
static void _cnav_add_symbol(cnav_v27_part_t *part, u8 ch)
|
||||
{
|
||||
part->symbols[part->n_symbols++] = ch;
|
||||
part->symbols[part->n_symbols++] = ch;
|
||||
|
||||
if (part->init) {
|
||||
/* Initial step - load more symbols without decoding. */
|
||||
if (part->n_symbols < (GPS_L2C_V27_INIT_BITS + GPS_L2C_V27_DECODE_BITS) * 2) {
|
||||
return;
|
||||
}
|
||||
part->init = false;
|
||||
}
|
||||
else if (part->n_symbols < GPS_L2C_V27_DECODE_BITS * 2) {
|
||||
/* Wait until decoding block is accumulated */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Feed accumulated symbols into the buffer, reset the number of accumulated
|
||||
* symbols. */
|
||||
v27_update(&part->dec, part->symbols, part->n_symbols / 2);
|
||||
part->n_symbols = 0;
|
||||
|
||||
/* Decode N+M bits, where:
|
||||
* - N - Number of bits to put into decoded buffer
|
||||
* - M - Number of bits in the tail to ignore.
|
||||
*/
|
||||
unsigned char tmp_bits[ (GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS +
|
||||
CHAR_BIT - 1) / CHAR_BIT];
|
||||
|
||||
v27_chainback_likely(&part->dec, tmp_bits,
|
||||
GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS);
|
||||
|
||||
/* Read decoded bits and add them to the decoded buffer */
|
||||
bitcopy(part->decoded, part->n_decoded, tmp_bits, 0, GPS_L2C_V27_DECODE_BITS);
|
||||
part->n_decoded += GPS_L2C_V27_DECODE_BITS;
|
||||
|
||||
/* Depending on the decoder state, one of the following actions are
|
||||
* possible:
|
||||
* - If no message lock
|
||||
* - If no preamble seen - look for preamble
|
||||
* - If preamble seen - collect 300 bits
|
||||
* - If 300 bits are collected - verify CRC
|
||||
* - If CRC is OK - message lock is acquired
|
||||
* - If CRC fails - rescan for preamble
|
||||
* - If found - continue collecting 300 bits
|
||||
* - If not found - continue preamble wait
|
||||
* - If message lock
|
||||
* - If 300 bits collected, compute CRC
|
||||
* - If CRC is OK, message can be decoded
|
||||
* - If CRC is not OK, discard data
|
||||
*/
|
||||
|
||||
bool retry = true;
|
||||
while (retry) {
|
||||
retry = false;
|
||||
|
||||
if (!part->preamble_seen) {
|
||||
/* Rescan for preamble if possible. The first bit is ignored. */
|
||||
_cnav_rescan_preamble(part);
|
||||
}
|
||||
if (part->preamble_seen && GPS_CNAV_MSG_LENGTH <= part->n_decoded) {
|
||||
|
||||
/* We have collected 300 bits starting from message preamble. Now try
|
||||
* to compute CRC-24Q */
|
||||
u32 crc = _cnav_compute_crc(part);
|
||||
u32 crc2 = _cnav_extract_crc(part);
|
||||
|
||||
if (part->message_lock) {
|
||||
/* We have message lock */
|
||||
part->crc_ok = (crc == crc2);
|
||||
if (part->crc_ok) {
|
||||
/* Reset message lock counter */
|
||||
part->n_crc_fail = 0;
|
||||
} else {
|
||||
/* Increment message lock counter */
|
||||
part->n_crc_fail++;
|
||||
if (part->n_crc_fail > GPS_CNAV_LOCK_MAX_CRC_FAILS) {
|
||||
/* CRC has failed too many times - drop the lock. */
|
||||
part->n_crc_fail = 0;
|
||||
part->message_lock = false;
|
||||
part->preamble_seen = false;
|
||||
/* Try to find a new preamble, reuse data from buffer. */
|
||||
retry = true;
|
||||
}
|
||||
if (part->init)
|
||||
{
|
||||
/* Initial step - load more symbols without decoding. */
|
||||
if (part->n_symbols < (GPS_L2C_V27_INIT_BITS + GPS_L2C_V27_DECODE_BITS) * 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
part->init = false;
|
||||
}
|
||||
else if (part->n_symbols < GPS_L2C_V27_DECODE_BITS * 2)
|
||||
{
|
||||
/* Wait until decoding block is accumulated */
|
||||
return;
|
||||
}
|
||||
} else if (crc == crc2) {
|
||||
/* CRC match - message can be decoded */
|
||||
part->message_lock = true;
|
||||
part->crc_ok = true;
|
||||
part->n_crc_fail = 0;
|
||||
} else {
|
||||
/* There is no message lock and the CRC check fails. Assume there is
|
||||
* false positive lock - rescan for preamble. */
|
||||
part->crc_ok = false;
|
||||
part->preamble_seen = false;
|
||||
|
||||
/* CRC mismatch - try to re-scan for preamble */
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No preamble or preamble and less than 300 bits decoded */
|
||||
}
|
||||
}
|
||||
/* Feed accumulated symbols into the buffer, reset the number of accumulated
|
||||
* symbols. */
|
||||
v27_update(&part->dec, part->symbols, part->n_symbols / 2);
|
||||
part->n_symbols = 0;
|
||||
|
||||
/* Decode N+M bits, where:
|
||||
* - N - Number of bits to put into decoded buffer
|
||||
* - M - Number of bits in the tail to ignore.
|
||||
*/
|
||||
unsigned char tmp_bits[ (GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS +
|
||||
CHAR_BIT - 1) / CHAR_BIT];
|
||||
|
||||
v27_chainback_likely(&part->dec, tmp_bits,
|
||||
GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS);
|
||||
|
||||
/* Read decoded bits and add them to the decoded buffer */
|
||||
bitcopy(part->decoded, part->n_decoded, tmp_bits, 0, GPS_L2C_V27_DECODE_BITS);
|
||||
part->n_decoded += GPS_L2C_V27_DECODE_BITS;
|
||||
|
||||
/* Depending on the decoder state, one of the following actions are
|
||||
* possible:
|
||||
* - If no message lock
|
||||
* - If no preamble seen - look for preamble
|
||||
* - If preamble seen - collect 300 bits
|
||||
* - If 300 bits are collected - verify CRC
|
||||
* - If CRC is OK - message lock is acquired
|
||||
* - If CRC fails - rescan for preamble
|
||||
* - If found - continue collecting 300 bits
|
||||
* - If not found - continue preamble wait
|
||||
* - If message lock
|
||||
* - If 300 bits collected, compute CRC
|
||||
* - If CRC is OK, message can be decoded
|
||||
* - If CRC is not OK, discard data
|
||||
*/
|
||||
|
||||
bool retry = true;
|
||||
while (retry)
|
||||
{
|
||||
retry = false;
|
||||
|
||||
if (!part->preamble_seen)
|
||||
{
|
||||
/* Rescan for preamble if possible. The first bit is ignored. */
|
||||
_cnav_rescan_preamble(part);
|
||||
}
|
||||
if (part->preamble_seen && GPS_CNAV_MSG_LENGTH <= part->n_decoded)
|
||||
{
|
||||
|
||||
/* We have collected 300 bits starting from message preamble. Now try
|
||||
* to compute CRC-24Q */
|
||||
u32 crc = _cnav_compute_crc(part);
|
||||
u32 crc2 = _cnav_extract_crc(part);
|
||||
|
||||
if (part->message_lock)
|
||||
{
|
||||
/* We have message lock */
|
||||
part->crc_ok = (crc == crc2);
|
||||
if (part->crc_ok)
|
||||
{
|
||||
/* Reset message lock counter */
|
||||
part->n_crc_fail = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment message lock counter */
|
||||
part->n_crc_fail++;
|
||||
if (part->n_crc_fail > GPS_CNAV_LOCK_MAX_CRC_FAILS)
|
||||
{
|
||||
/* CRC has failed too many times - drop the lock. */
|
||||
part->n_crc_fail = 0;
|
||||
part->message_lock = false;
|
||||
part->preamble_seen = false;
|
||||
/* Try to find a new preamble, reuse data from buffer. */
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (crc == crc2)
|
||||
{
|
||||
/* CRC match - message can be decoded */
|
||||
part->message_lock = true;
|
||||
part->crc_ok = true;
|
||||
part->n_crc_fail = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no message lock and the CRC check fails. Assume there is
|
||||
* false positive lock - rescan for preamble. */
|
||||
part->crc_ok = false;
|
||||
part->preamble_seen = false;
|
||||
|
||||
/* CRC mismatch - try to re-scan for preamble */
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No preamble or preamble and less than 300 bits decoded */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invert message bits in the buffer.
|
||||
*
|
||||
@ -259,11 +305,14 @@ static void _cnav_add_symbol(cnav_v27_part_t *part, u8 ch)
|
||||
*/
|
||||
static void _cnav_msg_invert(cnav_v27_part_t *part)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(part->decoded); i++) {
|
||||
part->decoded[i] ^= 0xFFu;
|
||||
}
|
||||
size_t i = 0;
|
||||
for (i = 0; i < sizeof(part->decoded); i++)
|
||||
{
|
||||
part->decoded[i] ^= 0xFFu;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs CNAV message decoding.
|
||||
*
|
||||
@ -286,39 +335,45 @@ static void _cnav_msg_invert(cnav_v27_part_t *part)
|
||||
*/
|
||||
static bool _cnav_msg_decode(cnav_v27_part_t *part, cnav_msg_t *msg, u32 *delay)
|
||||
{
|
||||
bool res = false;
|
||||
if (GPS_CNAV_MSG_LENGTH <= part->n_decoded) {
|
||||
if (part->crc_ok) {
|
||||
/* CRC is OK */
|
||||
if (part->invert) {
|
||||
_cnav_msg_invert(part);
|
||||
}
|
||||
bool res = false;
|
||||
if (GPS_CNAV_MSG_LENGTH <= part->n_decoded)
|
||||
{
|
||||
if (part->crc_ok)
|
||||
{
|
||||
/* CRC is OK */
|
||||
if (part->invert)
|
||||
{
|
||||
_cnav_msg_invert(part);
|
||||
}
|
||||
|
||||
msg->prn = getbitu(part->decoded, 8, 6);
|
||||
msg->msg_id = getbitu(part->decoded, 14, 6);
|
||||
msg->tow = getbitu(part->decoded, 20, 17);
|
||||
msg->alert = getbitu(part->decoded, 37, 1) ? true : false;
|
||||
msg->prn = getbitu(part->decoded, 8, 6);
|
||||
msg->msg_id = getbitu(part->decoded, 14, 6);
|
||||
msg->tow = getbitu(part->decoded, 20, 17);
|
||||
msg->alert = getbitu(part->decoded, 37, 1) ? true : false;
|
||||
|
||||
/* copy RAW message for GNSS-SDR */
|
||||
memcpy(msg->raw_msg,part->decoded,GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS);
|
||||
/* copy RAW message for GNSS-SDR */
|
||||
memcpy(msg->raw_msg,part->decoded,GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS);
|
||||
|
||||
*delay = (part->n_decoded - GPS_CNAV_MSG_LENGTH + GPS_L2C_V27_DELAY_BITS)
|
||||
* 2 + part->n_symbols;
|
||||
*delay = (part->n_decoded - GPS_CNAV_MSG_LENGTH + GPS_L2C_V27_DELAY_BITS) * 2 + part->n_symbols;
|
||||
|
||||
if (part->invert) {
|
||||
_cnav_msg_invert(part);
|
||||
}
|
||||
res = true;
|
||||
} else {
|
||||
/* CRC mismatch - no decoding */
|
||||
}
|
||||
bitshl(part->decoded, sizeof(part->decoded), GPS_CNAV_MSG_LENGTH);
|
||||
part->n_decoded -= GPS_CNAV_MSG_LENGTH;
|
||||
}
|
||||
if (part->invert)
|
||||
{
|
||||
_cnav_msg_invert(part);
|
||||
}
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CRC mismatch - no decoding */
|
||||
}
|
||||
bitshl(part->decoded, sizeof(part->decoded), GPS_CNAV_MSG_LENGTH);
|
||||
part->n_decoded -= GPS_CNAV_MSG_LENGTH;
|
||||
}
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize CNAV decoder.
|
||||
*
|
||||
@ -331,20 +386,20 @@ static bool _cnav_msg_decode(cnav_v27_part_t *part, cnav_msg_t *msg, u32 *delay)
|
||||
*/
|
||||
void cnav_msg_decoder_init(cnav_msg_decoder_t *dec)
|
||||
{
|
||||
memset(dec, 0, sizeof(*dec));
|
||||
v27_init(&dec->part1.dec,
|
||||
dec->part1.decisions,
|
||||
GPS_L2_V27_HISTORY_LENGTH_BITS,
|
||||
cnav_msg_decoder_get_poly(),
|
||||
0);
|
||||
v27_init(&dec->part2.dec,
|
||||
dec->part2.decisions,
|
||||
GPS_L2_V27_HISTORY_LENGTH_BITS,
|
||||
cnav_msg_decoder_get_poly(),
|
||||
0);
|
||||
dec->part1.init = true;
|
||||
dec->part2.init = true;
|
||||
_cnav_add_symbol(&dec->part2, 0x80);
|
||||
memset(dec, 0, sizeof(*dec));
|
||||
v27_init(&dec->part1.dec,
|
||||
dec->part1.decisions,
|
||||
GPS_L2_V27_HISTORY_LENGTH_BITS,
|
||||
cnav_msg_decoder_get_poly(),
|
||||
0);
|
||||
v27_init(&dec->part2.dec,
|
||||
dec->part2.decisions,
|
||||
GPS_L2_V27_HISTORY_LENGTH_BITS,
|
||||
cnav_msg_decoder_get_poly(),
|
||||
0);
|
||||
dec->part1.init = true;
|
||||
dec->part2.init = true;
|
||||
_cnav_add_symbol(&dec->part2, 0x80);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -370,29 +425,32 @@ void cnav_msg_decoder_init(cnav_msg_decoder_t *dec)
|
||||
* \retval false More data is required.
|
||||
*/
|
||||
bool cnav_msg_decoder_add_symbol(cnav_msg_decoder_t *dec,
|
||||
u8 symbol,
|
||||
cnav_msg_t *msg,
|
||||
u32 *pdelay)
|
||||
u8 symbol,
|
||||
cnav_msg_t *msg,
|
||||
u32 *pdelay)
|
||||
{
|
||||
_cnav_add_symbol(&dec->part1, symbol);
|
||||
_cnav_add_symbol(&dec->part2, symbol);
|
||||
_cnav_add_symbol(&dec->part1, symbol);
|
||||
_cnav_add_symbol(&dec->part2, symbol);
|
||||
|
||||
if (dec->part1.message_lock) {
|
||||
/* Flush data in decoder. */
|
||||
dec->part2.n_decoded = 0;
|
||||
dec->part2.n_symbols = 0;
|
||||
return _cnav_msg_decode(&dec->part1, msg, pdelay);
|
||||
}
|
||||
if (dec->part2.message_lock) {
|
||||
/* Flush data in decoder. */
|
||||
dec->part1.n_decoded = 0;
|
||||
dec->part1.n_symbols = 0;
|
||||
return _cnav_msg_decode(&dec->part2, msg, pdelay);
|
||||
}
|
||||
if (dec->part1.message_lock)
|
||||
{
|
||||
/* Flush data in decoder. */
|
||||
dec->part2.n_decoded = 0;
|
||||
dec->part2.n_symbols = 0;
|
||||
return _cnav_msg_decode(&dec->part1, msg, pdelay);
|
||||
}
|
||||
if (dec->part2.message_lock)
|
||||
{
|
||||
/* Flush data in decoder. */
|
||||
dec->part1.n_decoded = 0;
|
||||
dec->part1.n_symbols = 0;
|
||||
return _cnav_msg_decode(&dec->part2, msg, pdelay);
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides a singleton polynomial object.
|
||||
*
|
||||
@ -405,27 +463,28 @@ bool cnav_msg_decoder_add_symbol(cnav_msg_decoder_t *dec,
|
||||
*/
|
||||
const v27_poly_t *cnav_msg_decoder_get_poly(void)
|
||||
{
|
||||
static v27_poly_t instance;
|
||||
static bool initialized = false;
|
||||
static v27_poly_t instance;
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
/* Coefficients for polynomial object */
|
||||
const signed char coeffs[2] = { GPS_L2C_V27_POLY_A, GPS_L2C_V27_POLY_B };
|
||||
if (!initialized)
|
||||
{
|
||||
/* Coefficients for polynomial object */
|
||||
const signed char coeffs[2] = { GPS_L2C_V27_POLY_A, GPS_L2C_V27_POLY_B };
|
||||
|
||||
/* Racing condition handling: the data can be potential initialized more
|
||||
* than once in case multiple threads request concurrent access. However,
|
||||
* nature of the v27_poly_init() function and data alignment ensure that
|
||||
* the data returned from the earlier finished call is consistent and can
|
||||
* be used even when re-initialization is happening.
|
||||
*
|
||||
* Other possible approaches are:
|
||||
* - Replace late initialization with an explicit call.
|
||||
* - Use POSIX synchronization objects like pthread_once_t.
|
||||
*/
|
||||
v27_poly_init(&instance, coeffs);
|
||||
initialized = true;
|
||||
}
|
||||
return &instance;
|
||||
/* Racing condition handling: the data can be potential initialized more
|
||||
* than once in case multiple threads request concurrent access. However,
|
||||
* nature of the v27_poly_init() function and data alignment ensure that
|
||||
* the data returned from the earlier finished call is consistent and can
|
||||
* be used even when re-initialization is happening.
|
||||
*
|
||||
* Other possible approaches are:
|
||||
* - Replace late initialization with an explicit call.
|
||||
* - Use POSIX synchronization objects like pthread_once_t.
|
||||
*/
|
||||
v27_poly_init(&instance, coeffs);
|
||||
initialized = true;
|
||||
}
|
||||
return &instance;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1,15 +1,35 @@
|
||||
/*
|
||||
/*!
|
||||
* \file cnav_msg.h
|
||||
* \author Valeri Atamaniouk <valeri@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2016 Swift Navigation Inc.
|
||||
* Contact: Valeri Atamaniouk <valeri@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIBSWIFTNAV_CNAV_MSG_H
|
||||
#define LIBSWIFTNAV_CNAV_MSG_H
|
||||
|
||||
@ -42,11 +62,11 @@
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
u8 prn; /**< SV PRN. 0..31 */
|
||||
u8 msg_id; /**< Message id. 0..31 */
|
||||
u32 tow; /**< GPS ToW in 6-second units. Multiply to 6 to get seconds. */
|
||||
bool alert; /**< CNAV message alert flag */
|
||||
u8 raw_msg[GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS]; /**< RAW MSG for GNSS-SDR */
|
||||
u8 prn; /**< SV PRN. 0..31 */
|
||||
u8 msg_id; /**< Message id. 0..31 */
|
||||
u32 tow; /**< GPS ToW in 6-second units. Multiply to 6 to get seconds. */
|
||||
bool alert; /**< CNAV message alert flag */
|
||||
u8 raw_msg[GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS]; /**< RAW MSG for GNSS-SDR */
|
||||
} cnav_msg_t;
|
||||
|
||||
/**
|
||||
@ -56,24 +76,24 @@ typedef struct
|
||||
* @sa cnav_msg_decoder_t
|
||||
*/
|
||||
typedef struct {
|
||||
v27_t dec; /**< Viterbi block decoder object */
|
||||
v27_decision_t decisions[GPS_L2_V27_HISTORY_LENGTH_BITS];
|
||||
/**< Decision graph */
|
||||
unsigned char symbols[(GPS_L2C_V27_INIT_BITS + GPS_L2C_V27_DECODE_BITS) * 2];
|
||||
/**< Symbol buffer */
|
||||
size_t n_symbols; /**< Count of symbols in the symbol buffer */
|
||||
unsigned char decoded[GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS];
|
||||
/**< Decode buffer */
|
||||
size_t n_decoded; /**< Number of bits in the decode buffer */
|
||||
bool preamble_seen; /**< When true, the decode buffer is aligned on
|
||||
* preamble. */
|
||||
bool invert; /**< When true, indicates the bits are inverted */
|
||||
bool message_lock; /**< When true, indicates the message boundary
|
||||
* is found. */
|
||||
bool crc_ok; /**< Flag that the last message had good CRC */
|
||||
size_t n_crc_fail; /**< Counter for CRC failures */
|
||||
bool init; /**< Initial state flag. When true, initial bits
|
||||
* do not produce output. */
|
||||
v27_t dec; /**< Viterbi block decoder object */
|
||||
v27_decision_t decisions[GPS_L2_V27_HISTORY_LENGTH_BITS];
|
||||
/**< Decision graph */
|
||||
unsigned char symbols[(GPS_L2C_V27_INIT_BITS + GPS_L2C_V27_DECODE_BITS) * 2];
|
||||
/**< Symbol buffer */
|
||||
size_t n_symbols; /**< Count of symbols in the symbol buffer */
|
||||
unsigned char decoded[GPS_L2C_V27_DECODE_BITS + GPS_L2C_V27_DELAY_BITS];
|
||||
/**< Decode buffer */
|
||||
size_t n_decoded; /**< Number of bits in the decode buffer */
|
||||
bool preamble_seen; /**< When true, the decode buffer is aligned on
|
||||
* preamble. */
|
||||
bool invert; /**< When true, indicates the bits are inverted */
|
||||
bool message_lock; /**< When true, indicates the message boundary
|
||||
* is found. */
|
||||
bool crc_ok; /**< Flag that the last message had good CRC */
|
||||
size_t n_crc_fail; /**< Counter for CRC failures */
|
||||
bool init; /**< Initial state flag. When true, initial bits
|
||||
* do not produce output. */
|
||||
} cnav_v27_part_t;
|
||||
|
||||
/**
|
||||
@ -84,8 +104,8 @@ typedef struct {
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
cnav_v27_part_t part1; /**< Decoder for odd symbol pairs */
|
||||
cnav_v27_part_t part2; /**< Decoder for even symbol pairs */
|
||||
cnav_v27_part_t part1; /**< Decoder for odd symbol pairs */
|
||||
cnav_v27_part_t part2; /**< Decoder for even symbol pairs */
|
||||
} cnav_msg_decoder_t;
|
||||
|
||||
const v27_poly_t *cnav_msg_decoder_get_poly(void);
|
||||
|
@ -1,13 +1,32 @@
|
||||
/*
|
||||
/*!
|
||||
* \file edc.c
|
||||
* \author Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2010 Swift Navigation Inc.
|
||||
* Contact: Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "edc.h"
|
||||
@ -21,38 +40,38 @@
|
||||
* \{ */
|
||||
|
||||
static const u32 crc24qtab[256] = {
|
||||
0x000000, 0x864CFB, 0x8AD50D, 0x0C99F6, 0x93E6E1, 0x15AA1A, 0x1933EC, 0x9F7F17,
|
||||
0xA18139, 0x27CDC2, 0x2B5434, 0xAD18CF, 0x3267D8, 0xB42B23, 0xB8B2D5, 0x3EFE2E,
|
||||
0xC54E89, 0x430272, 0x4F9B84, 0xC9D77F, 0x56A868, 0xD0E493, 0xDC7D65, 0x5A319E,
|
||||
0x64CFB0, 0xE2834B, 0xEE1ABD, 0x685646, 0xF72951, 0x7165AA, 0x7DFC5C, 0xFBB0A7,
|
||||
0x0CD1E9, 0x8A9D12, 0x8604E4, 0x00481F, 0x9F3708, 0x197BF3, 0x15E205, 0x93AEFE,
|
||||
0xAD50D0, 0x2B1C2B, 0x2785DD, 0xA1C926, 0x3EB631, 0xB8FACA, 0xB4633C, 0x322FC7,
|
||||
0xC99F60, 0x4FD39B, 0x434A6D, 0xC50696, 0x5A7981, 0xDC357A, 0xD0AC8C, 0x56E077,
|
||||
0x681E59, 0xEE52A2, 0xE2CB54, 0x6487AF, 0xFBF8B8, 0x7DB443, 0x712DB5, 0xF7614E,
|
||||
0x19A3D2, 0x9FEF29, 0x9376DF, 0x153A24, 0x8A4533, 0x0C09C8, 0x00903E, 0x86DCC5,
|
||||
0xB822EB, 0x3E6E10, 0x32F7E6, 0xB4BB1D, 0x2BC40A, 0xAD88F1, 0xA11107, 0x275DFC,
|
||||
0xDCED5B, 0x5AA1A0, 0x563856, 0xD074AD, 0x4F0BBA, 0xC94741, 0xC5DEB7, 0x43924C,
|
||||
0x7D6C62, 0xFB2099, 0xF7B96F, 0x71F594, 0xEE8A83, 0x68C678, 0x645F8E, 0xE21375,
|
||||
0x15723B, 0x933EC0, 0x9FA736, 0x19EBCD, 0x8694DA, 0x00D821, 0x0C41D7, 0x8A0D2C,
|
||||
0xB4F302, 0x32BFF9, 0x3E260F, 0xB86AF4, 0x2715E3, 0xA15918, 0xADC0EE, 0x2B8C15,
|
||||
0xD03CB2, 0x567049, 0x5AE9BF, 0xDCA544, 0x43DA53, 0xC596A8, 0xC90F5E, 0x4F43A5,
|
||||
0x71BD8B, 0xF7F170, 0xFB6886, 0x7D247D, 0xE25B6A, 0x641791, 0x688E67, 0xEEC29C,
|
||||
0x3347A4, 0xB50B5F, 0xB992A9, 0x3FDE52, 0xA0A145, 0x26EDBE, 0x2A7448, 0xAC38B3,
|
||||
0x92C69D, 0x148A66, 0x181390, 0x9E5F6B, 0x01207C, 0x876C87, 0x8BF571, 0x0DB98A,
|
||||
0xF6092D, 0x7045D6, 0x7CDC20, 0xFA90DB, 0x65EFCC, 0xE3A337, 0xEF3AC1, 0x69763A,
|
||||
0x578814, 0xD1C4EF, 0xDD5D19, 0x5B11E2, 0xC46EF5, 0x42220E, 0x4EBBF8, 0xC8F703,
|
||||
0x3F964D, 0xB9DAB6, 0xB54340, 0x330FBB, 0xAC70AC, 0x2A3C57, 0x26A5A1, 0xA0E95A,
|
||||
0x9E1774, 0x185B8F, 0x14C279, 0x928E82, 0x0DF195, 0x8BBD6E, 0x872498, 0x016863,
|
||||
0xFAD8C4, 0x7C943F, 0x700DC9, 0xF64132, 0x693E25, 0xEF72DE, 0xE3EB28, 0x65A7D3,
|
||||
0x5B59FD, 0xDD1506, 0xD18CF0, 0x57C00B, 0xC8BF1C, 0x4EF3E7, 0x426A11, 0xC426EA,
|
||||
0x2AE476, 0xACA88D, 0xA0317B, 0x267D80, 0xB90297, 0x3F4E6C, 0x33D79A, 0xB59B61,
|
||||
0x8B654F, 0x0D29B4, 0x01B042, 0x87FCB9, 0x1883AE, 0x9ECF55, 0x9256A3, 0x141A58,
|
||||
0xEFAAFF, 0x69E604, 0x657FF2, 0xE33309, 0x7C4C1E, 0xFA00E5, 0xF69913, 0x70D5E8,
|
||||
0x4E2BC6, 0xC8673D, 0xC4FECB, 0x42B230, 0xDDCD27, 0x5B81DC, 0x57182A, 0xD154D1,
|
||||
0x26359F, 0xA07964, 0xACE092, 0x2AAC69, 0xB5D37E, 0x339F85, 0x3F0673, 0xB94A88,
|
||||
0x87B4A6, 0x01F85D, 0x0D61AB, 0x8B2D50, 0x145247, 0x921EBC, 0x9E874A, 0x18CBB1,
|
||||
0xE37B16, 0x6537ED, 0x69AE1B, 0xEFE2E0, 0x709DF7, 0xF6D10C, 0xFA48FA, 0x7C0401,
|
||||
0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, 0xDD8538
|
||||
0x000000, 0x864CFB, 0x8AD50D, 0x0C99F6, 0x93E6E1, 0x15AA1A, 0x1933EC, 0x9F7F17,
|
||||
0xA18139, 0x27CDC2, 0x2B5434, 0xAD18CF, 0x3267D8, 0xB42B23, 0xB8B2D5, 0x3EFE2E,
|
||||
0xC54E89, 0x430272, 0x4F9B84, 0xC9D77F, 0x56A868, 0xD0E493, 0xDC7D65, 0x5A319E,
|
||||
0x64CFB0, 0xE2834B, 0xEE1ABD, 0x685646, 0xF72951, 0x7165AA, 0x7DFC5C, 0xFBB0A7,
|
||||
0x0CD1E9, 0x8A9D12, 0x8604E4, 0x00481F, 0x9F3708, 0x197BF3, 0x15E205, 0x93AEFE,
|
||||
0xAD50D0, 0x2B1C2B, 0x2785DD, 0xA1C926, 0x3EB631, 0xB8FACA, 0xB4633C, 0x322FC7,
|
||||
0xC99F60, 0x4FD39B, 0x434A6D, 0xC50696, 0x5A7981, 0xDC357A, 0xD0AC8C, 0x56E077,
|
||||
0x681E59, 0xEE52A2, 0xE2CB54, 0x6487AF, 0xFBF8B8, 0x7DB443, 0x712DB5, 0xF7614E,
|
||||
0x19A3D2, 0x9FEF29, 0x9376DF, 0x153A24, 0x8A4533, 0x0C09C8, 0x00903E, 0x86DCC5,
|
||||
0xB822EB, 0x3E6E10, 0x32F7E6, 0xB4BB1D, 0x2BC40A, 0xAD88F1, 0xA11107, 0x275DFC,
|
||||
0xDCED5B, 0x5AA1A0, 0x563856, 0xD074AD, 0x4F0BBA, 0xC94741, 0xC5DEB7, 0x43924C,
|
||||
0x7D6C62, 0xFB2099, 0xF7B96F, 0x71F594, 0xEE8A83, 0x68C678, 0x645F8E, 0xE21375,
|
||||
0x15723B, 0x933EC0, 0x9FA736, 0x19EBCD, 0x8694DA, 0x00D821, 0x0C41D7, 0x8A0D2C,
|
||||
0xB4F302, 0x32BFF9, 0x3E260F, 0xB86AF4, 0x2715E3, 0xA15918, 0xADC0EE, 0x2B8C15,
|
||||
0xD03CB2, 0x567049, 0x5AE9BF, 0xDCA544, 0x43DA53, 0xC596A8, 0xC90F5E, 0x4F43A5,
|
||||
0x71BD8B, 0xF7F170, 0xFB6886, 0x7D247D, 0xE25B6A, 0x641791, 0x688E67, 0xEEC29C,
|
||||
0x3347A4, 0xB50B5F, 0xB992A9, 0x3FDE52, 0xA0A145, 0x26EDBE, 0x2A7448, 0xAC38B3,
|
||||
0x92C69D, 0x148A66, 0x181390, 0x9E5F6B, 0x01207C, 0x876C87, 0x8BF571, 0x0DB98A,
|
||||
0xF6092D, 0x7045D6, 0x7CDC20, 0xFA90DB, 0x65EFCC, 0xE3A337, 0xEF3AC1, 0x69763A,
|
||||
0x578814, 0xD1C4EF, 0xDD5D19, 0x5B11E2, 0xC46EF5, 0x42220E, 0x4EBBF8, 0xC8F703,
|
||||
0x3F964D, 0xB9DAB6, 0xB54340, 0x330FBB, 0xAC70AC, 0x2A3C57, 0x26A5A1, 0xA0E95A,
|
||||
0x9E1774, 0x185B8F, 0x14C279, 0x928E82, 0x0DF195, 0x8BBD6E, 0x872498, 0x016863,
|
||||
0xFAD8C4, 0x7C943F, 0x700DC9, 0xF64132, 0x693E25, 0xEF72DE, 0xE3EB28, 0x65A7D3,
|
||||
0x5B59FD, 0xDD1506, 0xD18CF0, 0x57C00B, 0xC8BF1C, 0x4EF3E7, 0x426A11, 0xC426EA,
|
||||
0x2AE476, 0xACA88D, 0xA0317B, 0x267D80, 0xB90297, 0x3F4E6C, 0x33D79A, 0xB59B61,
|
||||
0x8B654F, 0x0D29B4, 0x01B042, 0x87FCB9, 0x1883AE, 0x9ECF55, 0x9256A3, 0x141A58,
|
||||
0xEFAAFF, 0x69E604, 0x657FF2, 0xE33309, 0x7C4C1E, 0xFA00E5, 0xF69913, 0x70D5E8,
|
||||
0x4E2BC6, 0xC8673D, 0xC4FECB, 0x42B230, 0xDDCD27, 0x5B81DC, 0x57182A, 0xD154D1,
|
||||
0x26359F, 0xA07964, 0xACE092, 0x2AAC69, 0xB5D37E, 0x339F85, 0x3F0673, 0xB94A88,
|
||||
0x87B4A6, 0x01F85D, 0x0D61AB, 0x8B2D50, 0x145247, 0x921EBC, 0x9E874A, 0x18CBB1,
|
||||
0xE37B16, 0x6537ED, 0x69AE1B, 0xEFE2E0, 0x709DF7, 0xF6D10C, 0xFA48FA, 0x7C0401,
|
||||
0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, 0xDD8538
|
||||
};
|
||||
|
||||
/** Calculate Qualcomm 24-bit Cyclical Redundancy Check (CRC-24Q).
|
||||
@ -72,9 +91,10 @@ static const u32 crc24qtab[256] = {
|
||||
*/
|
||||
u32 crc24q(const u8 *buf, u32 len, u32 crc)
|
||||
{
|
||||
for (u32 i = 0; i < len; i++)
|
||||
crc = ((crc << 8) & 0xFFFFFF) ^ crc24qtab[((crc >> 16) ^ buf[i]) & 0xff];
|
||||
return crc;
|
||||
u32 i = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
crc = ((crc << 8) & 0xFFFFFF) ^ crc24qtab[((crc >> 16) ^ buf[i]) & 0xff];
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,26 +114,30 @@ u32 crc24q(const u8 *buf, u32 len, u32 crc)
|
||||
*/
|
||||
u32 crc24q_bits(u32 crc, const u8 *buf, u32 n_bits, bool invert)
|
||||
{
|
||||
u16 acc = 0;
|
||||
u8 b = 0;
|
||||
u32 shift = 8 - n_bits % 8;
|
||||
u16 acc = 0;
|
||||
u8 b = 0;
|
||||
u32 shift = 8 - n_bits % 8;
|
||||
|
||||
for (u32 i = 0; i < n_bits / 8; ++i) {
|
||||
acc = (acc << 8) | *buf++;
|
||||
if (invert) {
|
||||
acc ^= 0xFFu;
|
||||
}
|
||||
u32 i = 0;
|
||||
for (i = 0; i < n_bits / 8; ++i)
|
||||
{
|
||||
acc = (acc << 8) | *buf++;
|
||||
if (invert)
|
||||
{
|
||||
acc ^= 0xFFu;
|
||||
}
|
||||
b = (acc >> shift) & 0xFFu;
|
||||
crc = ((crc << 8) & 0xFFFFFFu) ^ crc24qtab[((crc >> 16) ^ b) & 0xFFu];
|
||||
}
|
||||
acc = (acc << 8) | *buf;
|
||||
if (invert)
|
||||
{
|
||||
acc ^= 0xFFu;
|
||||
}
|
||||
b = (acc >> shift) & 0xFFu;
|
||||
crc = ((crc << 8) & 0xFFFFFFu) ^ crc24qtab[((crc >> 16) ^ b) & 0xFFu];
|
||||
}
|
||||
acc = (acc << 8) | *buf;
|
||||
if (invert) {
|
||||
acc ^= 0xFFu;
|
||||
}
|
||||
b = (acc >> shift) & 0xFFu;
|
||||
crc = ((crc << 8) & 0xFFFFFFu) ^ crc24qtab[((crc >> 16) ^ b) & 0xFFu];
|
||||
|
||||
return crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +1,35 @@
|
||||
/*
|
||||
/*!
|
||||
* \file edc.h
|
||||
* \author Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2010 Swift Navigation Inc.
|
||||
* Contact: Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIBSWIFTNAV_EDC_H
|
||||
#define LIBSWIFTNAV_EDC_H
|
||||
|
||||
|
@ -1,10 +1,36 @@
|
||||
/* User include file for libfec
|
||||
* Copyright 2004, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||
/*!
|
||||
* \file fec.h
|
||||
* \author Phil Karn, KA9Q
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2004, Phil Karn, KA9Q
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FEC_H_
|
||||
#define _FEC_H_
|
||||
|
||||
#ifndef LIBSWIFTNAV_FEC_H_
|
||||
#define LIBSWIFTNAV_FEC_H_
|
||||
|
||||
/* r=1/2 k=7 convolutional encoder polynomials
|
||||
* The NASA-DSN convention is to use V27POLYA inverted, then V27POLYB
|
||||
@ -14,25 +40,25 @@
|
||||
#define V27POLYB 0x6d
|
||||
|
||||
typedef struct {
|
||||
unsigned char c0[32];
|
||||
unsigned char c1[32];
|
||||
unsigned char c0[32];
|
||||
unsigned char c1[32];
|
||||
} v27_poly_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int w[2];
|
||||
unsigned int w[2];
|
||||
} v27_decision_t;
|
||||
|
||||
/* State info for instance of r=1/2 k=7 Viterbi decoder
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int metrics1[64]; /* Path metric buffer 1 */
|
||||
unsigned int metrics2[64]; /* Path metric buffer 2 */
|
||||
/* Pointers to path metrics, swapped on every bit */
|
||||
unsigned int *old_metrics, *new_metrics;
|
||||
const v27_poly_t *poly; /* Polynomial to use */
|
||||
v27_decision_t *decisions; /* Beginning of decisions for block */
|
||||
unsigned int decisions_index; /* Index of current decision */
|
||||
unsigned int decisions_count; /* Number of decisions in history */
|
||||
unsigned int metrics1[64]; /* Path metric buffer 1 */
|
||||
unsigned int metrics2[64]; /* Path metric buffer 2 */
|
||||
/* Pointers to path metrics, swapped on every bit */
|
||||
unsigned int *old_metrics, *new_metrics;
|
||||
const v27_poly_t *poly; /* Polynomial to use */
|
||||
v27_decision_t *decisions; /* Beginning of decisions for block */
|
||||
unsigned int decisions_index; /* Index of current decision */
|
||||
unsigned int decisions_count; /* Number of decisions in history */
|
||||
} v27_t;
|
||||
|
||||
void v27_poly_init(v27_poly_t *poly, const signed char polynomial[2]);
|
||||
|
@ -1,16 +1,37 @@
|
||||
/*
|
||||
/*!
|
||||
* \file swift_common.h
|
||||
* \author Henry Hallam <henry@swift-nav.com>
|
||||
* Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2012 Swift Navigation Inc.
|
||||
* Contact: Henry Hallam <henry@swift-nav.com>
|
||||
* Fergus Noble <fergus@swift-nav.com>
|
||||
*
|
||||
* This source is subject to the license found in the file 'LICENSE' which must
|
||||
* be be distributed together with this source. All other rights reserved.
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIBSWIFTNAV_COMMON_H
|
||||
#define LIBSWIFTNAV_COMMON_H
|
||||
|
||||
|
@ -1,21 +1,48 @@
|
||||
/* K=7 r=1/2 Viterbi decoder in portable C
|
||||
* Copyright Feb 2004, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||
/*!
|
||||
* \file viterbi27.c
|
||||
* \author Phil Karn, KA9Q
|
||||
* \brief K=7 r=1/2 Viterbi decoder in portable C
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
* This file was originally borrowed from libswiftnav
|
||||
* <https://github.com/swift-nav/libswiftnav>,
|
||||
* a portable C library implementing GNSS related functions and algorithms,
|
||||
* and then modified by J. Arribas and C. Fernandez
|
||||
*
|
||||
* Copyright (C) 2004, Phil Karn, KA9Q
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* This file is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "fec.h"
|
||||
|
||||
static inline int parity(int x)
|
||||
{
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
x &= 0xf;
|
||||
return (0x6996 >> x) & 1;
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
x &= 0xf;
|
||||
return (0x6996 >> x) & 1;
|
||||
}
|
||||
|
||||
|
||||
/** Initialize a v27_poly_t struct for use with a v27_t decoder.
|
||||
*
|
||||
* \param poly Structure to initialize.
|
||||
@ -23,14 +50,16 @@ static inline int parity(int x)
|
||||
*/
|
||||
void v27_poly_init(v27_poly_t *poly, const signed char polynomial[2])
|
||||
{
|
||||
int state;
|
||||
int state;
|
||||
|
||||
for(state = 0; state < 32; state++) {
|
||||
poly->c0[state] = (polynomial[0] < 0) ^ parity((2*state) & abs(polynomial[0])) ? 255 : 0;
|
||||
poly->c1[state] = (polynomial[1] < 0) ^ parity((2*state) & abs(polynomial[1])) ? 255 : 0;
|
||||
}
|
||||
for(state = 0; state < 32; state++)
|
||||
{
|
||||
poly->c0[state] = (polynomial[0] < 0) ^ parity((2*state) & abs(polynomial[0])) ? 255 : 0;
|
||||
poly->c1[state] = (polynomial[1] < 0) ^ parity((2*state) & abs(polynomial[1])) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Initialize a v27_t struct for Viterbi decoding.
|
||||
*
|
||||
* \param v Structure to initialize
|
||||
@ -45,35 +74,36 @@ void v27_poly_init(v27_poly_t *poly, const signed char polynomial[2])
|
||||
void v27_init(v27_t *v, v27_decision_t *decisions, unsigned int decisions_count,
|
||||
const v27_poly_t *poly, unsigned char initial_state)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
v->old_metrics = v->metrics1;
|
||||
v->new_metrics = v->metrics2;
|
||||
v->poly = poly;
|
||||
v->decisions = decisions;
|
||||
v->decisions_index = 0;
|
||||
v->decisions_count = decisions_count;
|
||||
v->old_metrics = v->metrics1;
|
||||
v->new_metrics = v->metrics2;
|
||||
v->poly = poly;
|
||||
v->decisions = decisions;
|
||||
v->decisions_index = 0;
|
||||
v->decisions_count = decisions_count;
|
||||
|
||||
for(i = 0; i < 64; i++)
|
||||
v->old_metrics[i] = 63;
|
||||
for(i = 0; i < 64; i++)
|
||||
v->old_metrics[i] = 63;
|
||||
|
||||
v->old_metrics[initial_state & 63] = 0; /* Bias known start state */
|
||||
v->old_metrics[initial_state & 63] = 0; /* Bias known start state */
|
||||
}
|
||||
|
||||
|
||||
/* C-language butterfly */
|
||||
#define BFLY(i) {\
|
||||
unsigned int metric,m0,m1,decision;\
|
||||
metric = (v->poly->c0[i] ^ sym0) + (v->poly->c1[i] ^ sym1);\
|
||||
m0 = v->old_metrics[i] + metric;\
|
||||
m1 = v->old_metrics[i+32] + (510 - metric);\
|
||||
decision = (signed int)(m0-m1) > 0;\
|
||||
v->new_metrics[2*i] = decision ? m1 : m0;\
|
||||
d->w[i/16] |= decision << ((2*i)&31);\
|
||||
m0 -= (metric+metric-510);\
|
||||
m1 += (metric+metric-510);\
|
||||
decision = (signed int)(m0-m1) > 0;\
|
||||
v->new_metrics[2*i+1] = decision ? m1 : m0;\
|
||||
d->w[i/16] |= decision << ((2*i+1)&31);\
|
||||
unsigned int metric,m0,m1,decision;\
|
||||
metric = (v->poly->c0[i] ^ sym0) + (v->poly->c1[i] ^ sym1);\
|
||||
m0 = v->old_metrics[i] + metric;\
|
||||
m1 = v->old_metrics[i+32] + (510 - metric);\
|
||||
decision = (signed int)(m0-m1) > 0;\
|
||||
v->new_metrics[2*i] = decision ? m1 : m0;\
|
||||
d->w[i/16] |= decision << ((2*i)&31);\
|
||||
m0 -= (metric+metric-510);\
|
||||
m1 += (metric+metric-510);\
|
||||
decision = (signed int)(m0-m1) > 0;\
|
||||
v->new_metrics[2*i+1] = decision ? m1 : m0;\
|
||||
d->w[i/16] |= decision << ((2*i+1)&31);\
|
||||
}
|
||||
|
||||
/** Update a v27_t decoder with a block of symbols.
|
||||
@ -85,77 +115,81 @@ unsigned int metric,m0,m1,decision;\
|
||||
*/
|
||||
void v27_update(v27_t *v, const unsigned char *syms, int nbits)
|
||||
{
|
||||
unsigned char sym0, sym1;
|
||||
unsigned int *tmp;
|
||||
int normalize = 0;
|
||||
unsigned char sym0, sym1;
|
||||
unsigned int *tmp;
|
||||
int normalize = 0;
|
||||
|
||||
while(nbits--) {
|
||||
v27_decision_t *d = &v->decisions[v->decisions_index];
|
||||
while(nbits--)
|
||||
{
|
||||
v27_decision_t *d = &v->decisions[v->decisions_index];
|
||||
|
||||
d->w[0] = d->w[1] = 0;
|
||||
sym0 = *syms++;
|
||||
sym1 = *syms++;
|
||||
d->w[0] = d->w[1] = 0;
|
||||
sym0 = *syms++;
|
||||
sym1 = *syms++;
|
||||
|
||||
BFLY(0);
|
||||
BFLY(1);
|
||||
BFLY(2);
|
||||
BFLY(3);
|
||||
BFLY(4);
|
||||
BFLY(5);
|
||||
BFLY(6);
|
||||
BFLY(7);
|
||||
BFLY(8);
|
||||
BFLY(9);
|
||||
BFLY(10);
|
||||
BFLY(11);
|
||||
BFLY(12);
|
||||
BFLY(13);
|
||||
BFLY(14);
|
||||
BFLY(15);
|
||||
BFLY(16);
|
||||
BFLY(17);
|
||||
BFLY(18);
|
||||
BFLY(19);
|
||||
BFLY(20);
|
||||
BFLY(21);
|
||||
BFLY(22);
|
||||
BFLY(23);
|
||||
BFLY(24);
|
||||
BFLY(25);
|
||||
BFLY(26);
|
||||
BFLY(27);
|
||||
BFLY(28);
|
||||
BFLY(29);
|
||||
BFLY(30);
|
||||
BFLY(31);
|
||||
BFLY(0);
|
||||
BFLY(1);
|
||||
BFLY(2);
|
||||
BFLY(3);
|
||||
BFLY(4);
|
||||
BFLY(5);
|
||||
BFLY(6);
|
||||
BFLY(7);
|
||||
BFLY(8);
|
||||
BFLY(9);
|
||||
BFLY(10);
|
||||
BFLY(11);
|
||||
BFLY(12);
|
||||
BFLY(13);
|
||||
BFLY(14);
|
||||
BFLY(15);
|
||||
BFLY(16);
|
||||
BFLY(17);
|
||||
BFLY(18);
|
||||
BFLY(19);
|
||||
BFLY(20);
|
||||
BFLY(21);
|
||||
BFLY(22);
|
||||
BFLY(23);
|
||||
BFLY(24);
|
||||
BFLY(25);
|
||||
BFLY(26);
|
||||
BFLY(27);
|
||||
BFLY(28);
|
||||
BFLY(29);
|
||||
BFLY(30);
|
||||
BFLY(31);
|
||||
|
||||
/* Normalize metrics if they are nearing overflow */
|
||||
if(v->new_metrics[0] > (1<<30)) {
|
||||
int i;
|
||||
unsigned int minmetric = 1<<31;
|
||||
/* Normalize metrics if they are nearing overflow */
|
||||
if(v->new_metrics[0] > (1 << 30))
|
||||
{
|
||||
int i;
|
||||
unsigned int minmetric = 1 << 31;
|
||||
|
||||
for(i=0; i<64; i++) {
|
||||
if(v->new_metrics[i] < minmetric)
|
||||
minmetric = v->new_metrics[i];
|
||||
}
|
||||
for(i = 0; i < 64; i++)
|
||||
{
|
||||
if(v->new_metrics[i] < minmetric)
|
||||
minmetric = v->new_metrics[i];
|
||||
}
|
||||
|
||||
for(i=0; i<64; i++)
|
||||
v->new_metrics[i] -= minmetric;
|
||||
for(i = 0; i < 64; i++)
|
||||
v->new_metrics[i] -= minmetric;
|
||||
|
||||
normalize += minmetric;
|
||||
}
|
||||
normalize += minmetric;
|
||||
}
|
||||
|
||||
/* Advance decision index */
|
||||
if(++v->decisions_index >= v->decisions_count)
|
||||
v->decisions_index = 0;
|
||||
/* Advance decision index */
|
||||
if(++v->decisions_index >= v->decisions_count)
|
||||
v->decisions_index = 0;
|
||||
|
||||
/* Swap pointers to old and new metrics */
|
||||
tmp = v->old_metrics;
|
||||
v->old_metrics = v->new_metrics;
|
||||
v->new_metrics = tmp;
|
||||
}
|
||||
/* Swap pointers to old and new metrics */
|
||||
tmp = v->old_metrics;
|
||||
v->old_metrics = v->new_metrics;
|
||||
v->new_metrics = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Retrieve the most likely output bit sequence with known final state from
|
||||
* a v27_t decoder.
|
||||
*
|
||||
@ -167,28 +201,30 @@ void v27_update(v27_t *v, const unsigned char *syms, int nbits)
|
||||
void v27_chainback_fixed(v27_t *v, unsigned char *data, unsigned int nbits,
|
||||
unsigned char final_state)
|
||||
{
|
||||
int k;
|
||||
unsigned int decisions_index = v->decisions_index;
|
||||
int k;
|
||||
unsigned int decisions_index = v->decisions_index;
|
||||
|
||||
final_state %= 64;
|
||||
final_state <<= 2;
|
||||
final_state %= 64;
|
||||
final_state <<= 2;
|
||||
|
||||
while(nbits-- != 0) {
|
||||
while(nbits-- != 0)
|
||||
{
|
||||
|
||||
/* Decrement decision index */
|
||||
decisions_index = (decisions_index == 0) ?
|
||||
v->decisions_count-1 : decisions_index-1;
|
||||
/* Decrement decision index */
|
||||
decisions_index = (decisions_index == 0) ?
|
||||
v->decisions_count-1 : decisions_index-1;
|
||||
|
||||
v27_decision_t *d = &v->decisions[decisions_index];
|
||||
k = (d->w[(final_state>>2)/32] >> ((final_state>>2)%32)) & 1;
|
||||
/* The store into data[] only needs to be done every 8 bits.
|
||||
* But this avoids a conditional branch, and the writes will
|
||||
* combine in the cache anyway
|
||||
*/
|
||||
data[nbits>>3] = final_state = (final_state >> 1) | (k << 7);
|
||||
}
|
||||
v27_decision_t *d = &v->decisions[decisions_index];
|
||||
k = (d->w[(final_state >> 2) / 32] >> ((final_state >> 2) % 32)) & 1;
|
||||
/* The store into data[] only needs to be done every 8 bits.
|
||||
* But this avoids a conditional branch, and the writes will
|
||||
* combine in the cache anyway
|
||||
*/
|
||||
data[nbits >> 3] = final_state = (final_state >> 1) | (k << 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Retrieve the most likely output bit sequence with unknown final state from
|
||||
* a v27_t decoder.
|
||||
*
|
||||
@ -198,19 +234,19 @@ void v27_chainback_fixed(v27_t *v, unsigned char *data, unsigned int nbits,
|
||||
*/
|
||||
void v27_chainback_likely(v27_t *v, unsigned char *data, unsigned int nbits)
|
||||
{
|
||||
/* Determine state with minimum metric */
|
||||
/* Determine state with minimum metric */
|
||||
|
||||
int i;
|
||||
unsigned int best_metric = 0xffffffff;
|
||||
unsigned char best_state = 0;
|
||||
for(i=0; i<64; i++)
|
||||
{
|
||||
if(v->new_metrics[i] < best_metric)
|
||||
{
|
||||
best_metric = v->new_metrics[i];
|
||||
best_state = i;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
unsigned int best_metric = 0xffffffff;
|
||||
unsigned char best_state = 0;
|
||||
for(i = 0; i < 64; i++)
|
||||
{
|
||||
if(v->new_metrics[i] < best_metric)
|
||||
{
|
||||
best_metric = v->new_metrics[i];
|
||||
best_state = i;
|
||||
}
|
||||
}
|
||||
|
||||
v27_chainback_fixed(v, data, nbits, best_state);
|
||||
v27_chainback_fixed(v, data, nbits, best_state);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
*/
|
||||
|
||||
#include "gps_cnav_utc_model.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
Gps_CNAV_Utc_Model::Gps_CNAV_Utc_Model()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user