Implement a decoder covering COMMS from GOMSpace
This commit is contained in:
parent
c40b83211f
commit
ab45da4ad3
|
@ -9,3 +9,4 @@ apps/*.py
|
|||
.pyproject
|
||||
.pydevproject
|
||||
nbproject/
|
||||
.vscode
|
||||
|
|
|
@ -50,7 +50,9 @@ list(APPEND enabled_blocks
|
|||
satnogs_ogg_source.xml
|
||||
satnogs_noaa_apt_sink.xml
|
||||
satnogs_whitening.xml
|
||||
satnogs_whitening_ccsds.xml
|
||||
satnogs_ieee802_15_4_variant_decoder.xml
|
||||
satnogs_ax100_decoder.xml
|
||||
)
|
||||
|
||||
if(${INCLUDE_DEBUG_BLOCKS})
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>AX.100 Decoder Definition</name>
|
||||
<key>variable_ax100_decoder</key>
|
||||
<import>import satnogs</import>
|
||||
<var_make>self.$(id) = $(id) = satnogs.ax100_decoder_make($preamble, $preamble_thrsh, $sync_word, $sync_thrsh, $crc, $whitening, $rs)</var_make>
|
||||
<var_value>satnogs.ax100_decoder_make($preamble, $preamble_thrsh, $sync_word, $sync_thrsh, $crc, $whitening, $rs)</var_value>
|
||||
<make></make>
|
||||
<param>
|
||||
<name>Ignore Me</name>
|
||||
<key>value</key>
|
||||
<value>'ok'</value>
|
||||
<type>raw</type>
|
||||
<hide>all</hide>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Frame Preamble</name>
|
||||
<key>preamble</key>
|
||||
<value>[0x55, 0x55, 0x55, 0x55, 0x55]</value>
|
||||
<type>raw</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Preamble Threshold</name>
|
||||
<key>preamble_thrsh</key>
|
||||
<value>5</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Synchronization Word</name>
|
||||
<key>sync_word</key>
|
||||
<value>[0x31, 0xe5]</value>
|
||||
<type>raw</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Synchronization Word Threshold</name>
|
||||
<key>sync_thrsh</key>
|
||||
<value>3</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>CRC</name>
|
||||
<key>crc</key>
|
||||
<value>None</value>
|
||||
<type>raw</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Whitening</name>
|
||||
<key>whitening</key>
|
||||
<value>None</value>
|
||||
<type>raw</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Reed Solomon</name>
|
||||
<key>rs</key>
|
||||
<value>True</value>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>Enable</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Disable</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
</block>
|
|
@ -5,6 +5,7 @@
|
|||
<block>variable_ax25_decoder</block>
|
||||
<block>variable_amsat_duv_decoder</block>
|
||||
<block>variable_ieee802_15_4_variant_decoder</block>
|
||||
<block>variable_ax100_decoder</block>
|
||||
</cat>
|
||||
<cat>
|
||||
<name>Satellites</name>
|
||||
|
@ -40,5 +41,6 @@
|
|||
<block>satnogs_ax25_encoder_mb</block>
|
||||
<block>satnogs_waterfall_sink</block>
|
||||
<block>variable_whitening</block>
|
||||
<block>variable_whitening_ccsds</block>
|
||||
<block>satnogs_frame_decoder</block>
|
||||
</cat>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>CCSDS Whitening</name>
|
||||
<key>variable_whitening_ccsds</key>
|
||||
<import>import satnogs</import>
|
||||
<var_make>self.$(id) = $(id) = satnogs.whitening.make_ccsds()</var_make>
|
||||
<var_value>satnogs.whitening.make_ccsds()</var_value>
|
||||
<make></make>
|
||||
<param>
|
||||
<name>Ignore Me</name>
|
||||
<key>value</key>
|
||||
<value>'ok'</value>
|
||||
<type>raw</type>
|
||||
<hide>all</hide>
|
||||
</param>
|
||||
</block>
|
|
@ -28,6 +28,7 @@ list(APPEND DEBUG_HEADER_FILES
|
|||
)
|
||||
|
||||
list(APPEND HEADER_FILES
|
||||
ax100_decoder.h
|
||||
amsat_duv_decoder.h
|
||||
api.h
|
||||
ax25.h
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SATNOGS_AX100_DECODER_H
|
||||
#define INCLUDED_SATNOGS_AX100_DECODER_H
|
||||
|
||||
#include <satnogs/api.h>
|
||||
#include <satnogs/decoder.h>
|
||||
#include <satnogs/shift_reg.h>
|
||||
#include <satnogs/crc.h>
|
||||
#include <satnogs/whitening.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
/*!
|
||||
* \brief This decoder tries to cover all the supported framing and coding
|
||||
* schemes of the AX100 product from GOMSpace. It also supports some variants
|
||||
* that have appear in different missions, including excet the ASM and a
|
||||
* repeated preamble
|
||||
*
|
||||
*/
|
||||
class SATNOGS_API ax100_decoder : public decoder {
|
||||
public:
|
||||
static decoder_sptr
|
||||
make(const std::vector<uint8_t> &preamble,
|
||||
size_t preamble_threshold,
|
||||
const std::vector<uint8_t> &sync,
|
||||
size_t sync_threshold,
|
||||
crc::crc_t crc,
|
||||
whitening::whitening_sptr descrambler,
|
||||
bool enable_rs);
|
||||
|
||||
ax100_decoder(const std::vector<uint8_t> &preamble,
|
||||
size_t preamble_threshold,
|
||||
const std::vector<uint8_t> &sync,
|
||||
size_t sync_threshold,
|
||||
crc::crc_t crc,
|
||||
whitening::whitening_sptr descrambler,
|
||||
bool enable_rs);
|
||||
~ax100_decoder();
|
||||
|
||||
decoder_status_t
|
||||
decode(const void *in, int len);
|
||||
|
||||
void
|
||||
reset();
|
||||
|
||||
size_t
|
||||
input_multiple() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Decoding FSM
|
||||
*/
|
||||
typedef enum {
|
||||
SEARCHING, //!< when searching for the start of the preamble
|
||||
SEARCHING_SYNC, //!< We have preamble, search for sync
|
||||
DECODING_FRAME_LEN, //!< Decoding the frame length
|
||||
DECODING_PAYLOAD //!< Decoding the payload
|
||||
} decoding_state_t;
|
||||
|
||||
shift_reg d_preamble;
|
||||
shift_reg d_preamble_shift_reg;
|
||||
const size_t d_preamble_len;
|
||||
const size_t d_preamble_thrsh;
|
||||
shift_reg d_sync;
|
||||
shift_reg d_sync_shift_reg;
|
||||
const size_t d_sync_len;
|
||||
const size_t d_sync_thrsh;
|
||||
crc::crc_t d_crc;
|
||||
whitening::whitening_sptr d_descrambler;
|
||||
const bool d_rs;
|
||||
decoding_state_t d_state;
|
||||
size_t d_cnt;
|
||||
size_t d_len;
|
||||
size_t d_length_field_len;
|
||||
uint8_t *d_pdu;
|
||||
|
||||
int
|
||||
search_preamble(const uint8_t *in, int len);
|
||||
|
||||
int
|
||||
search_sync(const uint8_t *in, int len);
|
||||
|
||||
int
|
||||
decode_frame_len(const uint8_t *in, int len);
|
||||
|
||||
void
|
||||
decode_payload(decoder_status_t &status, const uint8_t *in, int len);
|
||||
|
||||
bool
|
||||
check_crc();
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_AX100_DECODER_H */
|
||||
|
|
@ -38,6 +38,7 @@ public:
|
|||
CRC16_CCITT_REVERSED,
|
||||
CRC16_AX25,
|
||||
CRC16_IBM,
|
||||
CRC32_C,
|
||||
CRC_METHODS_NUM
|
||||
} crc_t;
|
||||
|
||||
|
@ -53,12 +54,16 @@ public:
|
|||
static uint16_t
|
||||
crc16_ibm(const uint8_t *data, size_t len);
|
||||
|
||||
static uint32_t
|
||||
crc32_c(const uint8_t *data, size_t len);
|
||||
|
||||
static size_t
|
||||
crc_size(crc_t t);
|
||||
|
||||
private:
|
||||
static const uint16_t crc16_ccitt_table_reverse[256];
|
||||
static const uint16_t crc16_ccitt_table[256];
|
||||
static const uint32_t crc32_c_table[256];
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
private:
|
||||
/**
|
||||
* Decoding FSM
|
||||
* Decoding FSM states
|
||||
*/
|
||||
typedef enum {
|
||||
SEARCHING, //!< when searching for the start of the preamble
|
||||
|
|
|
@ -200,6 +200,15 @@ crc32(const uint8_t *buf, size_t len)
|
|||
return crc;
|
||||
}
|
||||
|
||||
static void
|
||||
print_pdu(const uint8_t *buf, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
printf("0x%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
} // namespace satnogs
|
||||
|
||||
} // namespace gr
|
||||
|
|
|
@ -44,6 +44,9 @@ public:
|
|||
static whitening_sptr
|
||||
make(uint32_t mask, uint32_t seed, uint32_t order);
|
||||
|
||||
static whitening_sptr
|
||||
make_ccsds();
|
||||
|
||||
whitening(uint32_t mask, uint32_t seed, uint32_t order);
|
||||
|
||||
~whitening();
|
||||
|
|
|
@ -76,7 +76,8 @@ list(APPEND satnogs_sources
|
|||
ax25_decoder.cc
|
||||
json_converter_impl.cc
|
||||
ieee802_15_4_variant_decoder.cc
|
||||
crc.cc)
|
||||
crc.cc
|
||||
ax100_decoder.cc)
|
||||
|
||||
if(${INCLUDE_DEBUG_BLOCKS})
|
||||
list(APPEND satnogs_sources ${satnogs_debug_sources})
|
||||
|
@ -129,6 +130,7 @@ list(APPEND test_satnogs_sources
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/qa_golay24.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_satnogs.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_satnogs.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_ax100_decoder.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_crc.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_ieee802_15_4_variant_decoder.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_json_converter.cc
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <satnogs/ax100_decoder.h>
|
||||
#include <satnogs/golay24.h>
|
||||
#include <satnogs/metadata.h>
|
||||
#include <satnogs/utils.h>
|
||||
#include <satnogs/log.h>
|
||||
|
||||
extern "C" {
|
||||
#include <fec.h>
|
||||
}
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
decoder::decoder_sptr
|
||||
ax100_decoder::make(const std::vector<uint8_t> &preamble,
|
||||
size_t preamble_threshold,
|
||||
const std::vector<uint8_t> &sync, size_t sync_threshold,
|
||||
crc::crc_t crc, whitening::whitening_sptr descrambler,
|
||||
bool enable_rs)
|
||||
{
|
||||
return decoder::decoder_sptr(
|
||||
new ax100_decoder(preamble, preamble_threshold, sync, sync_threshold,
|
||||
crc, descrambler, enable_rs));
|
||||
}
|
||||
|
||||
ax100_decoder::ax100_decoder(const std::vector<uint8_t> &preamble,
|
||||
size_t preamble_threshold,
|
||||
const std::vector<uint8_t> &sync,
|
||||
size_t sync_threshold,
|
||||
crc::crc_t crc,
|
||||
whitening::whitening_sptr descrambler,
|
||||
bool enable_rs) :
|
||||
decoder(sizeof(uint8_t), enable_rs ? 255 : 1024),
|
||||
d_preamble(preamble.size() * 8),
|
||||
d_preamble_shift_reg(preamble.size() * 8),
|
||||
d_preamble_len(preamble.size() * 8),
|
||||
d_preamble_thrsh(preamble_threshold),
|
||||
d_sync(sync.size() * 8),
|
||||
d_sync_shift_reg(sync.size() * 8),
|
||||
d_sync_len(sync.size() * 8),
|
||||
d_sync_thrsh(sync_threshold),
|
||||
d_crc(crc),
|
||||
d_descrambler(descrambler),
|
||||
d_rs(enable_rs),
|
||||
d_state(SEARCHING),
|
||||
d_cnt(0),
|
||||
d_len(0),
|
||||
/* Coded Golay 24 bits */
|
||||
d_length_field_len(3),
|
||||
d_pdu(new uint8_t[1024])
|
||||
{
|
||||
for (uint8_t b : preamble) {
|
||||
d_preamble <<= (b >> 7);
|
||||
d_preamble <<= ((b >> 6) & 0x1);
|
||||
d_preamble <<= ((b >> 5) & 0x1);
|
||||
d_preamble <<= ((b >> 4) & 0x1);
|
||||
d_preamble <<= ((b >> 3) & 0x1);
|
||||
d_preamble <<= ((b >> 2) & 0x1);
|
||||
d_preamble <<= ((b >> 1) & 0x1);
|
||||
d_preamble <<= (b & 0x1);
|
||||
}
|
||||
for (uint8_t b : sync) {
|
||||
d_sync <<= (b >> 7);
|
||||
d_sync <<= ((b >> 6) & 0x1);
|
||||
d_sync <<= ((b >> 5) & 0x1);
|
||||
d_sync <<= ((b >> 4) & 0x1);
|
||||
d_sync <<= ((b >> 3) & 0x1);
|
||||
d_sync <<= ((b >> 2) & 0x1);
|
||||
d_sync <<= ((b >> 1) & 0x1);
|
||||
d_sync <<= (b & 0x1);
|
||||
}
|
||||
|
||||
if (d_sync_len < 8) {
|
||||
throw std::invalid_argument("SYNC word should be at least 8 bits");
|
||||
}
|
||||
|
||||
if (d_preamble_len < 2 * d_preamble_thrsh) {
|
||||
throw std::invalid_argument(
|
||||
"Too many error bits are allowed for the preamble."
|
||||
"Consider lowering the threshold");
|
||||
}
|
||||
|
||||
if (d_sync_len < 2 * d_sync_thrsh) {
|
||||
throw std::invalid_argument(
|
||||
"Too many error bits are allowed for the sync word. "
|
||||
"Consider lowering the threshold");
|
||||
}
|
||||
}
|
||||
|
||||
ax100_decoder::~ax100_decoder()
|
||||
{
|
||||
delete[] d_pdu;
|
||||
}
|
||||
|
||||
decoder_status_t
|
||||
ax100_decoder::decode(const void *in, int len)
|
||||
{
|
||||
decoder_status_t status;
|
||||
switch (d_state) {
|
||||
case SEARCHING:
|
||||
status.consumed = search_preamble((const uint8_t *) in, len);
|
||||
break;
|
||||
case SEARCHING_SYNC:
|
||||
status.consumed = search_sync((const uint8_t *) in, len);
|
||||
break;
|
||||
case DECODING_FRAME_LEN:
|
||||
status.consumed = decode_frame_len((const uint8_t *) in, len);
|
||||
break;
|
||||
case DECODING_PAYLOAD:
|
||||
decode_payload(status, (const uint8_t *) in, len);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("ax100_decoder: Invalid decoding state");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
ax100_decoder::reset()
|
||||
{
|
||||
if (d_descrambler) {
|
||||
d_descrambler->reset();
|
||||
}
|
||||
d_cnt = 0;
|
||||
d_state = SEARCHING;
|
||||
d_preamble_shift_reg.reset();
|
||||
d_sync_shift_reg.reset();
|
||||
}
|
||||
|
||||
size_t
|
||||
ax100_decoder::input_multiple() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
int
|
||||
ax100_decoder::search_preamble(const uint8_t *in, int len)
|
||||
{
|
||||
/* We support also cases, where a repeated preamble is not used (pure CCSDS )*/
|
||||
if (d_preamble_len == 0) {
|
||||
d_state = SEARCHING_SYNC;
|
||||
return search_sync(in, len);
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
d_preamble_shift_reg <<= in[i];
|
||||
shift_reg tmp = d_preamble_shift_reg ^ d_preamble;
|
||||
if (tmp.count() <= d_preamble_thrsh) {
|
||||
d_state = SEARCHING_SYNC;
|
||||
d_cnt = 0;
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
ax100_decoder::search_sync(const uint8_t *in, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
d_sync_shift_reg <<= in[i];
|
||||
shift_reg tmp = d_sync_shift_reg ^ d_sync;
|
||||
d_cnt++;
|
||||
if (tmp.count() <= d_sync_thrsh) {
|
||||
LOG_WARN("Decoding");
|
||||
d_state = DECODING_FRAME_LEN;
|
||||
d_cnt = 0;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/* The sync word should be available by now */
|
||||
if (d_cnt > d_preamble_len * 2 + d_sync_len) {
|
||||
reset();
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
ax100_decoder::decode_frame_len(const uint8_t *in, int len)
|
||||
{
|
||||
const int s = len / 8;
|
||||
for (int i = 0; i < s; i++) {
|
||||
uint8_t b = 0x0;
|
||||
b = in[i * 8] << 7;
|
||||
b |= in[i * 8 + 1] << 6;
|
||||
b |= in[i * 8 + 2] << 5;
|
||||
b |= in[i * 8 + 3] << 4;
|
||||
b |= in[i * 8 + 4] << 3;
|
||||
b |= in[i * 8 + 5] << 2;
|
||||
b |= in[i * 8 + 6] << 1;
|
||||
b |= in[i * 8 + 7];
|
||||
d_pdu[d_cnt++] = b;
|
||||
|
||||
if (d_cnt == d_length_field_len) {
|
||||
uint32_t coded_len = (d_pdu[0] << 16) | (d_pdu[1] << 8) | d_pdu[2];
|
||||
print_pdu((const uint8_t *)&coded_len, 4);
|
||||
uint32_t len;
|
||||
golay24 g = golay24();
|
||||
if (g.decode24(&len, coded_len)) {
|
||||
d_len = len & 0xFF;
|
||||
//d_len += crc::crc_size(d_crc);
|
||||
LOG_WARN("Len: %u", d_len);
|
||||
if (d_len > max_frame_len()) {
|
||||
reset();
|
||||
return (i + 1) * 8;
|
||||
}
|
||||
/* All good! Proceed with decoding */
|
||||
d_cnt = 0;
|
||||
d_state = DECODING_PAYLOAD;
|
||||
memset(d_pdu, 0, max_frame_len());
|
||||
return (i + 1) * 8;
|
||||
}
|
||||
else {
|
||||
reset();
|
||||
return (i + 1) * 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
return s * 8;
|
||||
}
|
||||
|
||||
void
|
||||
ax100_decoder::decode_payload(decoder_status_t &status,
|
||||
const uint8_t *in, int len)
|
||||
{
|
||||
const int s = len / 8;
|
||||
for (int i = 0; i < s; i++) {
|
||||
uint8_t b = 0x0;
|
||||
b = in[i * 8] << 7;
|
||||
b |= in[i * 8 + 1] << 6;
|
||||
b |= in[i * 8 + 2] << 5;
|
||||
b |= in[i * 8 + 3] << 4;
|
||||
b |= in[i * 8 + 4] << 3;
|
||||
b |= in[i * 8 + 5] << 2;
|
||||
b |= in[i * 8 + 6] << 1;
|
||||
b |= in[i * 8 + 7];
|
||||
d_pdu[d_cnt++] = b;
|
||||
|
||||
if (d_cnt == d_len) {
|
||||
if (d_descrambler) {
|
||||
d_descrambler->descramble(d_pdu, d_pdu, d_len, false);
|
||||
}
|
||||
metadata::add_time_iso8601(status.data);
|
||||
/* If RS is used tru to decode the received frame */
|
||||
if (d_rs) {
|
||||
int ret = decode_rs_8(d_pdu, NULL, 0, 255 - d_len);
|
||||
/* Drop the parity */
|
||||
d_len -= 32;
|
||||
if (ret > - 1) {
|
||||
metadata::add_corrected_bits(status.data, ret);
|
||||
}
|
||||
else {
|
||||
reset();
|
||||
status.consumed = (i + 1) * 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
metadata::add_time_iso8601(status.data);
|
||||
metadata::add_pdu(status.data, d_pdu, d_len - crc::crc_size(d_crc));
|
||||
metadata::add_crc_valid(status.data, check_crc());
|
||||
reset();
|
||||
status.decode_success = true;
|
||||
status.consumed = (i + 1) * 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
status.consumed = s * 8;
|
||||
}
|
||||
|
||||
bool
|
||||
ax100_decoder::check_crc()
|
||||
{
|
||||
uint16_t crc16_c;
|
||||
uint16_t crc16_received;
|
||||
uint32_t crc32_c;
|
||||
uint32_t crc32_received;
|
||||
switch (d_crc) {
|
||||
case crc::CRC_NONE:
|
||||
return true;
|
||||
case crc::CRC32_C:
|
||||
crc32_c = crc::crc32_c(d_pdu, d_len - 4);
|
||||
memcpy(&crc32_received, d_pdu + d_len - 4, 4);
|
||||
crc32_received = ntohl(crc32_received);
|
||||
LOG_WARN("Received: 0x%02x Computed: 0x%02x", crc32_received, crc32_c);
|
||||
//print_pdu(d_pdu, d_len);
|
||||
if (crc32_c == crc32_received) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
throw std::runtime_error("ax100_decoder: Invalid CRC");
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
64
lib/crc.cc
64
lib/crc.cc
|
@ -93,6 +93,57 @@ const uint16_t crc::crc16_ccitt_table[256] = {
|
|||
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
|
||||
/*
|
||||
* Slicing-by-8 software
|
||||
*
|
||||
* The following CRC lookup table was generated automagically
|
||||
* using the following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
const uint32_t crc::crc32_c_table[256] = {
|
||||
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
|
||||
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
|
||||
0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
|
||||
0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
|
||||
0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
|
||||
0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
|
||||
0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
|
||||
0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
|
||||
0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
|
||||
0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
|
||||
0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
|
||||
0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
|
||||
0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
|
||||
0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
|
||||
0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
|
||||
0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
|
||||
0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
|
||||
0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
|
||||
0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
|
||||
0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
|
||||
0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
|
||||
0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
|
||||
0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
|
||||
0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
|
||||
0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
|
||||
0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
|
||||
0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
|
||||
0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
|
||||
0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
|
||||
0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
|
||||
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
|
||||
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
|
||||
};
|
||||
|
||||
uint16_t
|
||||
crc::crc16_ccitt_reversed(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
@ -165,11 +216,24 @@ crc::crc_size(crc_t t)
|
|||
case CRC16_AX25:
|
||||
case CRC16_IBM:
|
||||
return sizeof(uint16_t);
|
||||
case CRC32_C:
|
||||
return sizeof(uint32_t);
|
||||
default:
|
||||
throw std::invalid_argument("crc: Invalid CRC method");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc::crc32_c(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
crc = (crc >> 8) ^ crc::crc32_c_table[(crc ^ data[i]) & 0xff];
|
||||
}
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
||||
|
||||
|
||||
|
|
|
@ -326,6 +326,8 @@ ieee802_15_4_variant_decoder::check_crc()
|
|||
{
|
||||
uint16_t crc16_c;
|
||||
uint16_t crc16_received;
|
||||
uint32_t crc32_c;
|
||||
uint32_t crc32_received;
|
||||
switch (d_crc) {
|
||||
case crc::CRC_NONE:
|
||||
return true;
|
||||
|
@ -351,11 +353,20 @@ ieee802_15_4_variant_decoder::check_crc()
|
|||
crc16_c = crc::crc16_ibm(d_pdu, d_len + d_length_field_len - 2);
|
||||
memcpy(&crc16_received, d_pdu + d_length_field_len + d_len - 2, 2);
|
||||
crc16_received = ntohs(crc16_received);
|
||||
LOG_WARN("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c);
|
||||
LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c);
|
||||
if (crc16_c == crc16_received) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case crc::CRC32_C:
|
||||
crc32_c = crc::crc32_c(d_pdu, d_len + d_length_field_len - 4);
|
||||
memcpy(&crc32_received, d_pdu + d_length_field_len + d_len - 4, 4);
|
||||
crc32_received = ntohl(crc32_received);
|
||||
LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc32_received, crc32_c);
|
||||
if (crc32_c == crc32_received) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
throw std::runtime_error("ieee802_15_4_variant_decoder: Invalid CRC");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gnuradio/attributes.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include "qa_ax100_decoder.h"
|
||||
#include <satnogs/ax100_decoder.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
void
|
||||
qa_ax100_decoder::t1()
|
||||
{
|
||||
// Put test here
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QA_AX100_DECODER_H_
|
||||
#define _QA_AX100_DECODER_H_
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
class qa_ax100_decoder : public CppUnit::TestCase {
|
||||
public:
|
||||
CPPUNIT_TEST_SUITE(qa_ax100_decoder);
|
||||
CPPUNIT_TEST(t1);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void t1();
|
||||
};
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
||||
|
||||
#endif /* _QA_AX100_DECODER_H_ */
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include "qa_json_converter.h"
|
||||
#include "qa_ieee802_15_4_variant_decoder.h"
|
||||
#include "qa_crc.h"
|
||||
#include "qa_ax100_decoder.h"
|
||||
|
||||
CppUnit::TestSuite *
|
||||
qa_satnogs::suite()
|
||||
|
@ -34,5 +35,6 @@ qa_satnogs::suite()
|
|||
s->addTest(gr::satnogs::qa_json_converter::suite());
|
||||
s->addTest(gr::satnogs::qa_ieee802_15_4_variant_decoder::suite());
|
||||
s->addTest(gr::satnogs::qa_crc::suite());
|
||||
s->addTest(gr::satnogs::qa_ax100_decoder::suite());
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,6 @@ shift_reg::shift_reg(size_t len)
|
|||
: d_len(len),
|
||||
d_reg(len, 0)
|
||||
{
|
||||
if (len < 1) {
|
||||
throw std::invalid_argument("Shift register should contain at least one stage");
|
||||
}
|
||||
}
|
||||
|
||||
shift_reg::~shift_reg()
|
||||
|
|
|
@ -46,6 +46,17 @@ whitening::make(uint32_t mask, uint32_t seed, uint32_t order)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* CCSDS compliant data whitening
|
||||
* @return shared pointer to a CCSDS compliant scrambler/descrambler
|
||||
*/
|
||||
whitening::whitening_sptr
|
||||
whitening::make_ccsds()
|
||||
{
|
||||
return make(0xA9, 0xFF, 7);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Data whitening and de-whitening class
|
||||
* @param mask the polynomial mask
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
%{
|
||||
#include "satnogs/amsat_duv_decoder.h"
|
||||
#include "satnogs/ax100_decoder.h"
|
||||
#include "satnogs/ax25_decoder.h"
|
||||
#include "satnogs/morse_tree.h"
|
||||
#include "satnogs/morse_decoder.h"
|
||||
|
@ -53,8 +54,11 @@
|
|||
%include "satnogs/amsat_duv_decoder.h"
|
||||
%include "satnogs/ax25_decoder.h"
|
||||
%include "satnogs/metadata.h"
|
||||
|
||||
/* crc.h should come first. All classes using it should be included afterwards */
|
||||
%include "satnogs/crc.h"
|
||||
%include "satnogs/ieee802_15_4_variant_decoder.h"
|
||||
%include "satnogs/ax100_decoder.h"
|
||||
|
||||
%include "satnogs/morse_decoder.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder);
|
||||
|
|
Loading…
Reference in New Issue