Start the implementation of a generic frame synchronizer
The generic frame synchronizer will be able to adapt in a variety of common framing schemes used by popular modems.
This commit is contained in:
parent
2122b531ae
commit
4bcd9c8aaa
|
@ -1,7 +1,7 @@
|
||||||
image: debian:latest
|
image: debian:latest
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update -qq && apt-get install -y -qq gnuradio-dev libcppunit-dev libpng++-dev libvorbis-dev libnova-dev cmake swig pkg-config build-essential
|
- apt-get update -qq && apt-get install -y -qq gnuradio-dev libcppunit-dev libpng++-dev libvorbis-dev cmake swig pkg-config build-essential git
|
||||||
|
|
||||||
test:
|
test:
|
||||||
script:
|
script:
|
||||||
|
|
|
@ -51,6 +51,7 @@ list(APPEND enabled_blocks
|
||||||
satnogs_quad_demod_filter_ff.xml
|
satnogs_quad_demod_filter_ff.xml
|
||||||
satnogs_ogg_source.xml
|
satnogs_ogg_source.xml
|
||||||
satnogs_noaa_apt_sink.xml
|
satnogs_noaa_apt_sink.xml
|
||||||
|
satnogs_whitening.xml
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${INCLUDE_DEBUG_BLOCKS})
|
if(${INCLUDE_DEBUG_BLOCKS})
|
||||||
|
|
|
@ -41,4 +41,5 @@
|
||||||
<block>satnogs_quad_demod_filter_ff</block>
|
<block>satnogs_quad_demod_filter_ff</block>
|
||||||
<block>satnogs_ccsds_rs_decoder_mm</block>
|
<block>satnogs_ccsds_rs_decoder_mm</block>
|
||||||
<block>satnogs_decoder_8b10b</block>
|
<block>satnogs_decoder_8b10b</block>
|
||||||
|
<block>variable_whitening</block>
|
||||||
</cat>
|
</cat>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<block>
|
||||||
|
<name>Whitening</name>
|
||||||
|
<key>variable_whitening</key>
|
||||||
|
<import>import satnogs</import>
|
||||||
|
<var_make>self.$(id) = $(id) = satnogs.whitening_make($mask, $seed, $order)</var_make>
|
||||||
|
<var_value>satnogs.whitening_make($mask, $seed, $order)</var_value>
|
||||||
|
<make></make>
|
||||||
|
<param>
|
||||||
|
<name>Ignore Me</name>
|
||||||
|
<key>value</key>
|
||||||
|
<value>'ok'</value>
|
||||||
|
<type>raw</type>
|
||||||
|
<hide>all</hide>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Mask</name>
|
||||||
|
<key>mask</key>
|
||||||
|
<type>int</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Seed</name>
|
||||||
|
<key>seed</key>
|
||||||
|
<type>int</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Order</name>
|
||||||
|
<key>order</key>
|
||||||
|
<type>int</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
</block>
|
|
@ -22,6 +22,7 @@
|
||||||
#define INCLUDED_SATNOGS_FRAME_ACQUISITION_H
|
#define INCLUDED_SATNOGS_FRAME_ACQUISITION_H
|
||||||
|
|
||||||
#include <satnogs/api.h>
|
#include <satnogs/api.h>
|
||||||
|
#include <satnogs/whitening.h>
|
||||||
#include <gnuradio/sync_block.h>
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
|
@ -39,19 +40,42 @@ class SATNOGS_API frame_acquisition : virtual public gr::sync_block
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<frame_acquisition> sptr;
|
typedef boost::shared_ptr<frame_acquisition> sptr;
|
||||||
|
|
||||||
/*!
|
typedef enum {
|
||||||
* \brief Return a shared_ptr to a new instance of satnogs::frame_acquisition.
|
CRC_NONE = 0,
|
||||||
*
|
CRC16,
|
||||||
* To avoid accidental use of raw pointers, satnogs::frame_acquisition's
|
CRC32
|
||||||
* constructor is in a private implementation
|
} checksum_t;
|
||||||
* class. satnogs::frame_acquisition::make is the public interface for
|
|
||||||
* creating new instances.
|
|
||||||
*/
|
|
||||||
static sptr
|
static sptr
|
||||||
make (const std::vector<uint8_t>& preamble,
|
make_generic_var_len (const std::vector<uint8_t>& preamble,
|
||||||
size_t preamble_threshold,
|
size_t preamble_threshold,
|
||||||
const std::vector<uint8_t>& sync,
|
const std::vector<uint8_t>& sync,
|
||||||
size_t sync_threshold);
|
size_t sync_threshold,
|
||||||
|
size_t frame_size_len = 1,
|
||||||
|
checksum_t crc = CRC_NONE,
|
||||||
|
whitening::sptr descrambler = nullptr,
|
||||||
|
size_t max_frame_len = 2048);
|
||||||
|
|
||||||
|
static sptr
|
||||||
|
make_generic_const_len(const std::vector<uint8_t>& preamble,
|
||||||
|
size_t preamble_threshold,
|
||||||
|
const std::vector<uint8_t>& sync,
|
||||||
|
size_t sync_threshold,
|
||||||
|
size_t frame_len = 1,
|
||||||
|
checksum_t crc = CRC_NONE,
|
||||||
|
whitening::sptr descrambler = nullptr,
|
||||||
|
size_t max_frame_len = 2048);
|
||||||
|
|
||||||
|
static sptr
|
||||||
|
make_golay24_var_len (const std::vector<uint8_t>& preamble,
|
||||||
|
size_t preamble_threshold,
|
||||||
|
const std::vector<uint8_t>& sync,
|
||||||
|
size_t sync_threshold,
|
||||||
|
checksum_t crc = CRC_NONE,
|
||||||
|
whitening::sptr descrambler = nullptr,
|
||||||
|
size_t max_frame_len = 2048);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace satnogs
|
} // namespace satnogs
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <satnogs/api.h>
|
#include <satnogs/api.h>
|
||||||
#include <gnuradio/digital/lfsr.h>
|
#include <gnuradio/digital/lfsr.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
{
|
{
|
||||||
|
@ -36,25 +37,35 @@ namespace gr
|
||||||
class SATNOGS_API whitening
|
class SATNOGS_API whitening
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static int base_unique_id;
|
||||||
|
|
||||||
|
int
|
||||||
|
unique_id ();
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<whitening> sptr;
|
||||||
|
|
||||||
|
static sptr
|
||||||
|
make(uint32_t mask, uint32_t seed, uint32_t order);
|
||||||
|
|
||||||
whitening (uint32_t mask, uint32_t seed, uint32_t order);
|
whitening (uint32_t mask, uint32_t seed, uint32_t order);
|
||||||
|
|
||||||
void
|
void
|
||||||
reset ();
|
reset ();
|
||||||
|
|
||||||
void scramble(uint8_t *out, const uint8_t *in, size_t len,
|
void
|
||||||
bool msb = false);
|
scramble (uint8_t *out, const uint8_t *in, size_t len, bool msb = false);
|
||||||
void descramble(uint8_t *out, const uint8_t *in, size_t len,
|
void
|
||||||
bool msb = false);
|
descramble (uint8_t *out, const uint8_t *in, size_t len, bool msb = false);
|
||||||
|
|
||||||
void
|
void
|
||||||
scramble_one_bit_per_byte (uint8_t *out, const uint8_t *in,
|
scramble_one_bit_per_byte (uint8_t *out, const uint8_t *in, size_t bits_num);
|
||||||
size_t bits_num);
|
|
||||||
void
|
void
|
||||||
descramble_one_bit_per_byte (uint8_t *out, const uint8_t *in,
|
descramble_one_bit_per_byte (uint8_t *out, const uint8_t *in,
|
||||||
size_t bits_num);
|
size_t bits_num);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
digital::lfsr d_lfsr;
|
digital::lfsr d_lfsr;
|
||||||
|
int d_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace satnogs
|
} // namespace satnogs
|
||||||
|
|
|
@ -23,36 +23,96 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gnuradio/io_signature.h>
|
#include <gnuradio/io_signature.h>
|
||||||
|
|
||||||
#include "frame_acquisition_impl.h"
|
#include "frame_acquisition_impl.h"
|
||||||
|
|
||||||
|
#include <satnogs/golay24.h>
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
{
|
{
|
||||||
namespace satnogs
|
namespace satnogs
|
||||||
{
|
{
|
||||||
|
|
||||||
frame_acquisition::sptr
|
frame_acquisition::sptr
|
||||||
frame_acquisition::make (const std::vector<uint8_t>& preamble,
|
frame_acquisition::make_generic_var_len (const std::vector<uint8_t>& preamble,
|
||||||
size_t preamble_threshold,
|
size_t preamble_threshold,
|
||||||
const std::vector<uint8_t>& sync,
|
const std::vector<uint8_t>& sync,
|
||||||
size_t sync_threshold)
|
size_t sync_threshold,
|
||||||
|
size_t frame_size_len,
|
||||||
|
checksum_t crc,
|
||||||
|
whitening::sptr descrambler,
|
||||||
|
size_t max_frame_len)
|
||||||
{
|
{
|
||||||
return gnuradio::get_initial_sptr (
|
return gnuradio::get_initial_sptr (
|
||||||
new frame_acquisition_impl (preamble, preamble_threshold, sync,
|
new frame_acquisition_impl (frame_acquisition_impl::GENERIC_VAR_FRAME_LEN,
|
||||||
sync_threshold));
|
preamble,
|
||||||
|
preamble_threshold, sync, sync_threshold,
|
||||||
|
frame_size_len, 0, crc, descrambler,
|
||||||
|
max_frame_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_acquisition_impl::frame_acquisition_impl (
|
frame_acquisition::sptr
|
||||||
const std::vector<uint8_t>& preamble, size_t preamble_threshold,
|
frame_acquisition::make_generic_const_len (const std::vector<uint8_t>& preamble,
|
||||||
const std::vector<uint8_t>& sync, size_t sync_threshold) :
|
size_t preamble_threshold,
|
||||||
|
const std::vector<uint8_t>& sync,
|
||||||
|
size_t sync_threshold,
|
||||||
|
size_t frame_len, checksum_t crc,
|
||||||
|
whitening::sptr descrambler,
|
||||||
|
size_t max_frame_len)
|
||||||
|
{
|
||||||
|
return gnuradio::get_initial_sptr (
|
||||||
|
new frame_acquisition_impl (frame_acquisition_impl::GENERIC_CONSTANT_FRAME_LEN,
|
||||||
|
preamble,
|
||||||
|
preamble_threshold, sync, sync_threshold,
|
||||||
|
0, frame_len, crc, descrambler,
|
||||||
|
max_frame_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_acquisition::sptr
|
||||||
|
frame_acquisition::make_golay24_var_len (const std::vector<uint8_t>& preamble,
|
||||||
|
size_t preamble_threshold,
|
||||||
|
const std::vector<uint8_t>& sync,
|
||||||
|
size_t sync_threshold, checksum_t crc,
|
||||||
|
whitening::sptr descrambler,
|
||||||
|
size_t max_frame_len)
|
||||||
|
{
|
||||||
|
return gnuradio::get_initial_sptr (
|
||||||
|
new frame_acquisition_impl (frame_acquisition_impl::GOLAY24_CODED_FRAME_LEN,
|
||||||
|
preamble,
|
||||||
|
preamble_threshold, sync, sync_threshold,
|
||||||
|
0, 0, crc, descrambler,
|
||||||
|
max_frame_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_acquisition_impl::frame_acquisition_impl (variant_t variant,
|
||||||
|
const std::vector<uint8_t>& preamble,
|
||||||
|
size_t preamble_threshold,
|
||||||
|
const std::vector<uint8_t>& sync,
|
||||||
|
size_t sync_threshold,
|
||||||
|
size_t frame_size_len,
|
||||||
|
size_t frame_len,
|
||||||
|
checksum_t crc,
|
||||||
|
whitening::sptr descrambler,
|
||||||
|
size_t max_frame_len) :
|
||||||
gr::sync_block ("frame_acquisition",
|
gr::sync_block ("frame_acquisition",
|
||||||
gr::io_signature::make (1, 1, sizeof(uint8_t)),
|
gr::io_signature::make (1, 1, sizeof(uint8_t)),
|
||||||
gr::io_signature::make (0, 0, 0)),
|
gr::io_signature::make (0, 0, 0)),
|
||||||
|
d_variant(variant),
|
||||||
d_preamble(preamble.size() * 8),
|
d_preamble(preamble.size() * 8),
|
||||||
|
d_preamble_shift_reg(preamble.size() * 8),
|
||||||
d_preamble_len(preamble.size() * 8),
|
d_preamble_len(preamble.size() * 8),
|
||||||
d_preamble_thrsh(preamble_threshold),
|
d_preamble_thrsh(preamble_threshold),
|
||||||
d_sync(sync.size() * 8),
|
d_sync(sync.size() * 8),
|
||||||
|
d_sync_shift_reg(sync.size() * 8),
|
||||||
d_sync_len(sync.size() * 8),
|
d_sync_len(sync.size() * 8),
|
||||||
d_sync_thrsh(sync_threshold)
|
d_sync_thrsh(sync_threshold),
|
||||||
|
d_state(SEARCHING),
|
||||||
|
d_cnt(0),
|
||||||
|
d_frame_size_field_len(frame_size_len),
|
||||||
|
d_frame_len(frame_len),
|
||||||
|
d_max_frame_len(max_frame_len),
|
||||||
|
d_crc(crc),
|
||||||
|
d_whitening(descrambler)
|
||||||
{
|
{
|
||||||
set_output_multiple(8);
|
set_output_multiple(8);
|
||||||
for(uint8_t b : preamble) {
|
for(uint8_t b : preamble) {
|
||||||
|
@ -77,6 +137,45 @@ frame_acquisition_impl::frame_acquisition_impl (
|
||||||
d_sync <<= ((b >> 1) & 0x1);
|
d_sync <<= ((b >> 1) & 0x1);
|
||||||
d_sync <<= (b & 0x1);
|
d_sync <<= (b & 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parameters checking */
|
||||||
|
if (max_frame_len == 0) {
|
||||||
|
throw std::invalid_argument (
|
||||||
|
"The maximum frame size should be at least 1 byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d_sync_len < 8) {
|
||||||
|
throw std::invalid_argument("SYNC word should be at least 8 bits");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d_preamble_len < 8) {
|
||||||
|
throw std::invalid_argument("Preamble 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d_frame_size_field_len > 4) {
|
||||||
|
throw std::invalid_argument ("Frame length field can be up to 4 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d_frame_size_field_len == 0) {
|
||||||
|
throw std::invalid_argument ("Frame length field cannot be 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
d_pdu = new uint8_t[max_frame_len];
|
||||||
|
|
||||||
|
/* Register the PMT message queue */
|
||||||
|
message_port_register_out(pmt::mp("out"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -84,6 +183,7 @@ frame_acquisition_impl::frame_acquisition_impl (
|
||||||
*/
|
*/
|
||||||
frame_acquisition_impl::~frame_acquisition_impl ()
|
frame_acquisition_impl::~frame_acquisition_impl ()
|
||||||
{
|
{
|
||||||
|
delete [] d_pdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,11 +195,197 @@ frame_acquisition_impl::work (int noutput_items,
|
||||||
{
|
{
|
||||||
const uint8_t *in = (const uint8_t *) input_items[0];
|
const uint8_t *in = (const uint8_t *) input_items[0];
|
||||||
|
|
||||||
// Do <+signal processing+>
|
switch(d_state)
|
||||||
|
{
|
||||||
// Tell runtime system how many output items we produced.
|
case SEARCHING:
|
||||||
|
return searching_preamble(in, noutput_items);
|
||||||
|
case SEARCHING_SYNC:
|
||||||
|
return searching_sync(in, noutput_items);
|
||||||
|
case DECODING_GENERIC_FRAME_LEN:
|
||||||
|
return dec_generic_frame_len(in, noutput_items);
|
||||||
|
case DECODING_GOLAY24_FRAME_LEN:
|
||||||
|
return dec_golay24_frame_len(in, noutput_items);
|
||||||
|
case DECODING_PAYLOAD:
|
||||||
|
return decoding(in, noutput_items);
|
||||||
|
default:
|
||||||
return noutput_items;
|
return noutput_items;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
frame_acquisition_impl::searching_preamble (const uint8_t* in, int 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
|
||||||
|
frame_acquisition_impl::searching_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) {
|
||||||
|
switch(d_variant) {
|
||||||
|
case GENERIC_VAR_FRAME_LEN:
|
||||||
|
d_state = DECODING_GENERIC_FRAME_LEN;
|
||||||
|
break;
|
||||||
|
case GENERIC_CONSTANT_FRAME_LEN:
|
||||||
|
d_state = DECODING_GENERIC_FRAME_LEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len)
|
||||||
|
{
|
||||||
|
const int s = std::min(len / 8, (int) d_frame_size_field_len);
|
||||||
|
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_frame_len <<= 8;
|
||||||
|
d_frame_len |= b;
|
||||||
|
d_cnt++;
|
||||||
|
if(d_cnt == d_frame_size_field_len) {
|
||||||
|
|
||||||
|
/* Most of the available modems apply whitening on the frame length too */
|
||||||
|
if(d_whitening) {
|
||||||
|
uint32_t descrambled = 0x0;
|
||||||
|
d_whitening->descramble((uint8_t *)&descrambled,
|
||||||
|
(const uint8_t *)&d_frame_len,
|
||||||
|
d_frame_size_field_len, true);
|
||||||
|
d_frame_len = descrambled;
|
||||||
|
}
|
||||||
|
if(d_frame_len < d_max_frame_len) {
|
||||||
|
d_state = DECODING_PAYLOAD;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
reset();
|
||||||
|
return (i + 1) * 8;
|
||||||
|
}
|
||||||
|
d_cnt = 0;
|
||||||
|
return (i + 1) * 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len)
|
||||||
|
{
|
||||||
|
/* Golay24 needs 3 bytes to decode */
|
||||||
|
const int s = std::min(len / 8, 3);
|
||||||
|
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_frame_len <<= 8;
|
||||||
|
d_frame_len |= b;
|
||||||
|
d_cnt++;
|
||||||
|
|
||||||
|
/* Try to decode the frame length */
|
||||||
|
if (d_cnt == 3) {
|
||||||
|
if(d_whitening) {
|
||||||
|
uint32_t descrambled = 0x0;
|
||||||
|
d_whitening->descramble((uint8_t *)&descrambled,
|
||||||
|
(const uint8_t *)&d_frame_len, 3, true);
|
||||||
|
d_frame_len = descrambled;
|
||||||
|
}
|
||||||
|
golay24 g = golay24 ();
|
||||||
|
uint16_t tmp = 0;
|
||||||
|
if (g.decode24 (&tmp, d_frame_len)) {
|
||||||
|
d_frame_len = tmp;
|
||||||
|
/* Check if the payload can fit in the buffer */
|
||||||
|
if(d_frame_len > d_max_frame_len) {
|
||||||
|
reset();
|
||||||
|
return (i + 1) * 8;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
d_state = DECODING_PAYLOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reset ();
|
||||||
|
return (i + 1) * 8;
|
||||||
|
}
|
||||||
|
d_cnt = 0;
|
||||||
|
return (i + 1) * 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
frame_acquisition_impl::decoding (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_frame_len) {
|
||||||
|
if(d_whitening) {
|
||||||
|
d_whitening->descramble(d_pdu, d_pdu, d_frame_len, true);
|
||||||
|
}
|
||||||
|
/* TODO */
|
||||||
|
reset();
|
||||||
|
return (i+1) * 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
frame_acquisition_impl::reset ()
|
||||||
|
{
|
||||||
|
if(d_whitening) {
|
||||||
|
d_whitening->reset();
|
||||||
|
}
|
||||||
|
d_cnt = 0;
|
||||||
|
d_state = SEARCHING;
|
||||||
|
d_preamble_shift_reg.reset();
|
||||||
|
d_sync_shift_reg.reset();
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace satnogs */
|
} /* namespace satnogs */
|
||||||
} /* namespace gr */
|
} /* namespace gr */
|
||||||
|
|
|
@ -33,10 +33,23 @@ class frame_acquisition_impl : public frame_acquisition
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
frame_acquisition_impl (const std::vector<uint8_t>& preamble,
|
typedef enum {
|
||||||
|
GENERIC_VAR_FRAME_LEN = 0,
|
||||||
|
GENERIC_CONSTANT_FRAME_LEN,
|
||||||
|
GOLAY24_CODED_FRAME_LEN
|
||||||
|
} variant_t;
|
||||||
|
|
||||||
|
frame_acquisition_impl (variant_t variant,
|
||||||
|
const std::vector<uint8_t>& preamble,
|
||||||
size_t preamble_threshold,
|
size_t preamble_threshold,
|
||||||
const std::vector<uint8_t>& sync,
|
const std::vector<uint8_t>& sync,
|
||||||
size_t sync_threshold);
|
size_t sync_threshold,
|
||||||
|
size_t frame_size_len,
|
||||||
|
size_t frame_len,
|
||||||
|
checksum_t crc,
|
||||||
|
whitening::sptr descrambler,
|
||||||
|
size_t max_frame_len);
|
||||||
|
|
||||||
~frame_acquisition_impl ();
|
~frame_acquisition_impl ();
|
||||||
|
|
||||||
// Where all the action really happens
|
// Where all the action really happens
|
||||||
|
@ -45,12 +58,53 @@ public:
|
||||||
gr_vector_void_star &output_items);
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Decoding FSM
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SEARCHING, //!< when searching for the start of the preamble
|
||||||
|
SEARCHING_SYNC,
|
||||||
|
DECODING_GENERIC_FRAME_LEN,
|
||||||
|
DECODING_GOLAY24_FRAME_LEN,
|
||||||
|
DECODING_PAYLOAD
|
||||||
|
} decoding_state_t;
|
||||||
|
|
||||||
|
const variant_t d_variant;
|
||||||
shift_reg d_preamble;
|
shift_reg d_preamble;
|
||||||
|
shift_reg d_preamble_shift_reg;
|
||||||
const size_t d_preamble_len;
|
const size_t d_preamble_len;
|
||||||
const size_t d_preamble_thrsh;
|
const size_t d_preamble_thrsh;
|
||||||
shift_reg d_sync;
|
shift_reg d_sync;
|
||||||
|
shift_reg d_sync_shift_reg;
|
||||||
const size_t d_sync_len;
|
const size_t d_sync_len;
|
||||||
const size_t d_sync_thrsh;
|
const size_t d_sync_thrsh;
|
||||||
|
decoding_state_t d_state;
|
||||||
|
uint32_t d_cnt;
|
||||||
|
const uint32_t d_frame_size_field_len;
|
||||||
|
uint32_t d_frame_len;
|
||||||
|
const uint32_t d_max_frame_len;
|
||||||
|
const checksum_t d_crc;
|
||||||
|
whitening::sptr d_whitening;
|
||||||
|
uint8_t *d_pdu;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
searching_preamble(const uint8_t *in, int len);
|
||||||
|
|
||||||
|
int
|
||||||
|
searching_sync(const uint8_t *in, int len);
|
||||||
|
|
||||||
|
int dec_generic_frame_len(const uint8_t *in, int len);
|
||||||
|
|
||||||
|
|
||||||
|
int dec_golay24_frame_len(const uint8_t *in, int len);
|
||||||
|
|
||||||
|
int
|
||||||
|
decoding(const uint8_t *in, int len);
|
||||||
|
|
||||||
|
void
|
||||||
|
reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace satnogs
|
} // namespace satnogs
|
||||||
|
|
|
@ -31,6 +31,23 @@ namespace gr
|
||||||
namespace satnogs
|
namespace satnogs
|
||||||
{
|
{
|
||||||
|
|
||||||
|
int whitening::base_unique_id = 1;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data whitening and de-whitening class
|
||||||
|
* @param mask the polynomial mask
|
||||||
|
* @param seed the initial seed
|
||||||
|
* @param order the order of the shift register. This is equal to the
|
||||||
|
* number of memory stages.
|
||||||
|
*/
|
||||||
|
whitening::sptr
|
||||||
|
whitening::make (uint32_t mask, uint32_t seed, uint32_t order)
|
||||||
|
{
|
||||||
|
return whitening::sptr(new whitening(mask, seed, order));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data whitening and de-whitening class
|
* Data whitening and de-whitening class
|
||||||
* @param mask the polynomial mask
|
* @param mask the polynomial mask
|
||||||
|
@ -39,8 +56,16 @@ namespace satnogs
|
||||||
* number of memory stages.
|
* number of memory stages.
|
||||||
*/
|
*/
|
||||||
whitening::whitening (uint32_t mask, uint32_t seed, uint32_t order) :
|
whitening::whitening (uint32_t mask, uint32_t seed, uint32_t order) :
|
||||||
d_lfsr (mask, seed, order)
|
d_lfsr (mask, seed, order),
|
||||||
|
d_id(0)
|
||||||
{
|
{
|
||||||
|
d_id = base_unique_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
whitening::unique_id ()
|
||||||
|
{
|
||||||
|
return d_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue