Commit 92843c43 authored by Manolis Surligas's avatar Manolis Surligas

Add AX.25 encoder that supports the legacy hardware radios

The new encoder now supports NRZI and G3RUH scrambling that makes it
compatible with most of the FSK9600 modems.

Remove also some unneeded blocks.
parent bfa23132
......@@ -22,9 +22,7 @@ install(FILES
satnogs_morse_debug_source.xml
satnogs_multi_format_msg_sink.xml
satnogs_cw_to_symbol.xml
satnogs_afsk_decoder.xml
satnogs_sine_matched_filter_ff.xml
satnogs_ax25_encoder_bf.xml
satnogs_ax25_decoder_b.xml
satnogs_udp_msg_source.xml
satnogs_debug_msg_source.xml
......@@ -38,5 +36,6 @@ install(FILES
satnogs_udp_msg_sink.xml
satnogs_upsat_transmitter.xml
satnogs_coarse_doppler_correction_cc.xml
satnogs_debug_msg_source_raw.xml DESTINATION share/gnuradio/grc/blocks
satnogs_debug_msg_source_raw.xml
satnogs_ax25_encoder_mb.xml DESTINATION share/gnuradio/grc/blocks
)
<?xml version="1.0"?>
<block>
<name>afsk_decoder</name>
<key>satnogs_afsk_decoder</key>
<category>satnogs</category>
<import>import satnogs</import>
<make>satnogs.afsk_decoder($sampling_rate, $baudrate, $fft_size)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>...</name>
<key>...</key>
<type>...</type>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out</name>
<type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
</source>
</block>
<?xml version="1.0"?>
<block>
<name>AX.25 Encoder</name>
<key>satnogs_ax25_encoder_bf</key>
<key>satnogs_ax25_encoder_mb</key>
<category>satnogs</category>
<import>import satnogs</import>
<make>satnogs.ax25_encoder_bf($dest_addr, $dest_ssid, $src_addr, $src_ssid)</make>
<callback>set_address_field($dest_addr, $dest_ssid, $src_addr, $src_ssid)</callback>
<make>satnogs.ax25_encoder_mb($dest_addr, $dest_ssid, $src_addr, $src_ssid, $preamble_len, $postamble_len, $scramble)</make>
<param>
<name>Destination Callsign</name>
<key>dest_addr</key>
......@@ -30,14 +29,42 @@
<key>src_ssid</key>
<type>int</type>
</param>
<param>
<name>Preamble Length</name>
<key>preamble_len</key>
<value>16</value>
<type>int</type>
</param>
<param>
<name>Postamble Length</name>
<key>postamble_len</key>
<value>16</value>
<type>int</type>
</param>
<param>
<name>G3RUH Scrambling</name>
<key>scramble</key>
<type>enum</type>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<sink>
<name>info</name>
<type>message</type>
</sink>
<source>
<name>out</name>
<type>float</type>
<type>byte</type>
</source>
</block>
......@@ -32,10 +32,8 @@ install(FILES
morse_debug_source.h
multi_format_msg_sink.h
cw_to_symbol.h
afsk_decoder.h
sine_matched_filter_ff.h
utils.h
ax25_encoder_bf.h
ax25_decoder_b.h
udp_msg_source.h
debug_msg_source.h
......@@ -50,5 +48,6 @@ install(FILES
whitening.h
udp_msg_sink.h
coarse_doppler_correction_cc.h
debug_msg_source_raw.h DESTINATION include/satnogs
debug_msg_source_raw.h
ax25_encoder_mb.h DESTINATION include/satnogs
)
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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_AFSK_DECODER_H
#define INCLUDED_SATNOGS_AFSK_DECODER_H
#include <satnogs/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace satnogs {
/*!
* \brief AFSK decoder. This particular decoder uses a Frequency Domain
* approach to retrieve the message.
* \ingroup satnogs
*
*/
class SATNOGS_API afsk_decoder : virtual public gr::block
{
public:
typedef boost::shared_ptr<afsk_decoder> sptr;
/*!
* An AFSK decoder.
* @param sampling_rate the input sampling rate
* @param baudrate the baudrate (symbols per second)
* @param fft_size the FFT size that the decoder will use.
* @param auto_carrier_tracking if set to yes, the decoder will try
* to automatically find the mark and space frequencies
* @param mark_freq the frequency of the mark (1)
* @param mark_space the frequency of the space (0)
*/
static sptr make(double sampling_rate, size_t baudrate = 1200,
size_t fft_size = 128,
bool auto_carrier_tracking = false,
double mark_freq = 2400.0,
double space_freq = 1200.0);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_AFSK_DECODER_H */
......@@ -136,15 +136,18 @@ namespace gr
static inline size_t
ax25_prepare_frame (uint8_t *out, const uint8_t *info, size_t info_len,
ax25_frame_type_t type, uint8_t *addr, size_t addr_len,
uint16_t ctrl, size_t ctrl_len)
uint16_t ctrl, size_t ctrl_len, size_t preamble_len,
size_t postamble_len)
{
uint16_t fcs;
size_t i = 1;
size_t i;
if(info_len > AX25_MAX_FRAME_LEN) {
return 0;
}
out[0] = AX25_SYNC_FLAG;
memset(out, AX25_SYNC_FLAG, preamble_len);
i = preamble_len;
/* Insert address and control fields */
if( addr_len == AX25_MIN_ADDR_LEN || addr_len == AX25_MAX_ADDR_LEN){
memcpy(out + i, addr, addr_len);
......@@ -174,13 +177,13 @@ namespace gr
i += info_len;
/* Compute the FCS. Ignore the first flag byte */
fcs = ax25_fcs(out + 1, i - 1);
fcs = ax25_fcs(out + preamble_len, i - preamble_len);
/* The MS bits are sent first ONLY at the FCS field */
out[i++] = (fcs >> 8) & 0xFF;
out[i++] = fcs & 0xFF;
out[i++] = AX25_SYNC_FLAG;
out[i++] = (fcs >> 8) & 0xFF;
memset(out + i, AX25_SYNC_FLAG, postamble_len);
return i;
return i + postamble_len;
}
/**
......@@ -203,7 +206,8 @@ namespace gr
*/
static inline ax25_encode_status_t
ax25_nrz_bit_stuffing (float *out, size_t *out_len, const uint8_t *buffer,
const size_t buffer_len)
size_t buffer_len, size_t preamble_len,
size_t postamble_len)
{
uint8_t bit;
uint8_t prev_bit = 0;
......@@ -214,12 +218,14 @@ namespace gr
size_t i;
/* Leading FLAG field does not need bit stuffing */
memcpy(out, AX25_SYNC_FLAG_MAP, 8 * sizeof(float));
out_idx = 8;
for(i = 0; i < preamble_len; i++) {
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float));
out_idx += 8;
}
/* Skip the leading and trailing FLAG field */
buffer++;
for(i = 0; i < 8 * (buffer_len - 2); i++){
buffer += preamble_len;
for(i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++){
bit = (buffer[i / 8] >> ( i % 8)) & 0x1;
out[out_idx++] = bit ? 1.0 : -1.0;
......@@ -247,8 +253,10 @@ namespace gr
}
/* Trailing FLAG field does not need bit stuffing */
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float));
out_idx += 8;
for(i = 0; i < postamble_len; i++) {
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float));
out_idx += 8;
}
*out_len = out_idx;
return AX25_ENC_OK;
......@@ -274,7 +282,8 @@ namespace gr
*/
static inline ax25_encode_status_t
ax25_bit_stuffing (uint8_t *out, size_t *out_len, const uint8_t *buffer,
const size_t buffer_len)
const size_t buffer_len, size_t preamble_len,
size_t postamble_len)
{
uint8_t bit;
uint8_t prev_bit = 0;
......@@ -285,12 +294,14 @@ namespace gr
size_t i;
/* Leading FLAG field does not need bit stuffing */
memcpy(out, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t));
out_idx = 8;
for(i = 0; i < preamble_len; i++) {
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t));
out_idx += 8;
}
/* Skip the leading and trailing FLAG field */
buffer++;
for(i = 0; i < 8 * (buffer_len - 2); i++){
buffer += preamble_len;
for(i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++){
bit = (buffer[i / 8] >> ( i % 8)) & 0x1;
out[out_idx++] = bit;
......@@ -318,8 +329,10 @@ namespace gr
}
/* Trailing FLAG field does not need bit stuffing */
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t));
out_idx += 8;
for(i = 0; i < postamble_len; i++) {
memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t));
out_idx += 8;
}
*out_len = out_idx;
return AX25_ENC_OK;
......
......@@ -18,52 +18,61 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_AX25_ENCODER_BF_H
#define INCLUDED_SATNOGS_AX25_ENCODER_BF_H
#ifndef INCLUDED_SATNOGS_AX25_ENCODER_MB_H
#define INCLUDED_SATNOGS_AX25_ENCODER_MB_H
#include <satnogs/api.h>
#include <gnuradio/sync_block.h>
#include <satnogs/ax25.h>
namespace gr {
namespace satnogs {
namespace gr
{
namespace satnogs
{
/*!
* \brief AX.25 packet encoder
* \brief AX.25 encoder block that supports the legacy hardware radios.
*
* The block takes as inputs blob PMT messages and generates a byte stream.
* Each output byte contains only one LSB, thus the output can be directly
* used for FM modulation.
*
* \ingroup satnogs
*
*/
class SATNOGS_API ax25_encoder_bf : virtual public gr::sync_block
class SATNOGS_API ax25_encoder_mb : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<ax25_encoder_bf> sptr;
public:
typedef boost::shared_ptr<ax25_encoder_mb> sptr;
/**
* AX.25 packet encoder. This block receives messages containing
* the packet information, contracts a AX.25 packet end encodes it
* using NRZ.
* AX.25 encoder block that supports the legacy hardware radios.
*
* The block also creates suitable burst tags for proper
* burst transmission in SDR devices that support them.
* The block takes as inputs blob PMT messages and generates a byte stream.
* Each output byte contains only one LSB, thus the output can be directly
* used for FM modulation.
*
* @param dest_addr the destination callsign address
* @param dest_addr the destination callsign
* @param dest_ssid the destination SSID
* @param src_addr the callsign of the source
* @param src_addr the source callsign
* @param src_ssid the source SSID
* @param preamble_len the number of times that the AX.25 synchronization flags
* should be repeated in front of the frame.
* @param postamble_len the number of times that the AX.25 synchronization flags
* should be repeated at the end of the frame.
* @param scramble if set to true, G3RUH scrambling will be performed
* after bit stuffing
*/
static sptr make(std::string dest_addr,
uint8_t dest_ssid,
std::string src_addr,
uint8_t src_ssid);
virtual void
set_address_field (std::string dest_addr, uint8_t dest_ssid,
std::string src_addr, uint8_t src_ssid) = 0;
static sptr
make (const std::string& dest_addr, uint8_t dest_ssid,
const std::string& src_addr,
uint8_t src_ssid, size_t preamble_len =16,
size_t postamble_len = 16,
bool scramble = true);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_AX25_ENCODER_BF_H */
#endif /* INCLUDED_SATNOGS_AX25_ENCODER_MB_H */
......@@ -31,9 +31,7 @@ list(APPEND satnogs_sources
morse_debug_source_impl.cc
multi_format_msg_sink_impl.cc
cw_to_symbol_impl.cc
afsk_decoder_impl.cc
sine_matched_filter_ff_impl.cc
ax25_encoder_bf_impl.cc
ax25_decoder_b_impl.cc
udp_msg_source_impl.cc
debug_msg_source_impl.cc
......@@ -48,7 +46,8 @@ list(APPEND satnogs_sources
whitening.cc
udp_msg_sink_impl.cc
coarse_doppler_correction_cc_impl.cc
debug_msg_source_raw_impl.cc )
debug_msg_source_raw_impl.cc
ax25_encoder_mb_impl.cc )
set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE)
if(NOT satnogs_sources)
......
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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 "afsk_decoder_impl.h"
namespace gr
{
namespace satnogs
{
afsk_decoder::sptr
afsk_decoder::make (double sampling_rate, size_t samples_per_sym,
size_t fft_size,
bool auto_carrier_tracking,
double mark_freq,
double space_freq)
{
return gnuradio::get_initial_sptr (
new afsk_decoder_impl (sampling_rate, samples_per_sym, fft_size,
auto_carrier_tracking,
mark_freq, space_freq));
}
/*
* The private constructor
*/
afsk_decoder_impl::afsk_decoder_impl (double sampling_rate, size_t samples_per_sym,
size_t fft_size,
bool auto_carrier_tracking,
double mark_freq, double space_freq) :
gr::block ("afsk_decoder",
gr::io_signature::make (1, 1, fft_size * sizeof(float)),
gr::io_signature::make (1, 1, sizeof(char))),
d_samp_rate(sampling_rate),
d_samples_per_sym(samples_per_sym),
d_fft_size(fft_size),
d_carriers_found(!auto_carrier_tracking),
d_mark_freq(mark_freq),
d_space_freq(space_freq)
{
if(auto_carrier_tracking){
d_mark_freq = d_space_freq = 0.0;
}
}
/*
* Our virtual destructor.
*/
afsk_decoder_impl::~afsk_decoder_impl ()
{
}
void
afsk_decoder_impl::forecast (int noutput_items,
gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
}
int
afsk_decoder_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
consume_each (noutput_items);
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace satnogs */
} /* namespace gr */
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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_AFSK_DECODER_IMPL_H
#define INCLUDED_SATNOGS_AFSK_DECODER_IMPL_H
#include <satnogs/afsk_decoder.h>
namespace gr
{
namespace satnogs
{
class afsk_decoder_impl : public afsk_decoder
{
private:
const double d_samp_rate;
const size_t d_samples_per_sym;
const size_t d_fft_size;
bool d_carriers_found;
double d_mark_freq;
double d_space_freq;
public:
afsk_decoder_impl (double sampling_rate, size_t baudrate, size_t fft_size,
bool auto_carrier_tracking, double mark_freq,
double space_freq);
~afsk_decoder_impl ();
// Where all the action really happens
void
forecast (int noutput_items, gr_vector_int &ninput_items_required);
int
general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_AFSK_DECODER_IMPL_H */
......@@ -23,44 +23,54 @@
#endif
#include <gnuradio/io_signature.h>
#include "ax25_encoder_bf_impl.h"
#include "ax25_encoder_mb_impl.h"
#include <satnogs/log.h>
#include <satnogs/ax25.h>
namespace gr
{
namespace satnogs
{
ax25_encoder_bf::sptr
ax25_encoder_bf::make (std::string dest_addr,
uint8_t dest_ssid, std::string src_addr,
uint8_t src_ssid)
ax25_encoder_mb::sptr
ax25_encoder_mb::make (const std::string& dest_addr, uint8_t dest_ssid,
const std::string& src_addr, uint8_t src_ssid,
size_t preamble_len, size_t postamble_len,
bool scramble)
{
return gnuradio::get_initial_sptr (new ax25_encoder_bf_impl (AX25_I_FRAME,
dest_addr,
dest_ssid,
src_addr,
src_ssid));
return gnuradio::get_initial_sptr (
new ax25_encoder_mb_impl (dest_addr, dest_ssid, src_addr, src_ssid,
preamble_len, postamble_len, scramble));
}
/*
* The private constructor
*/
ax25_encoder_bf_impl::ax25_encoder_bf_impl (ax25_frame_type_t type,
std::string dest_addr,
ax25_encoder_mb_impl::ax25_encoder_mb_impl (const std::string& dest_addr,
uint8_t dest_ssid,
std::string src_addr,
uint8_t src_ssid) :
gr::sync_block ("ax25_encoder_bf", gr::io_signature::make (0, 0, 0),
gr::io_signature::make (1, 1, sizeof(float))),
d_type (type),
d_remaining (0),
d_produced(0),
d_endoded_frame(new float[(AX25_MAX_FRAME_LEN * 2)]),
d_tmp_buf(new uint8_t[AX25_MAX_FRAME_LEN * 2]),
d_addr_field(new uint8_t[AX25_MAX_ADDR_LEN])
const std::string& src_addr,
uint8_t src_ssid,
size_t preamble_len,
size_t postabmle_len,
bool scramble) :
gr::sync_block ("ax25_encoder_mb", gr::io_signature::make (0, 0, 0),
gr::io_signature::make (1, 1, sizeof(uint8_t))),
d_preamble_len (preamble_len),
d_postamble_len (postabmle_len),
d_scramble(scramble),
d_remaining (0),
d_produced (0),
d_prev_bit(0x0),
d_encoded_frame (
new uint8_t[preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)]),
d_tmp_buf (
new uint8_t[preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)]),
d_addr_field (new uint8_t[AX25_MAX_ADDR_LEN]),
d_lfsr(0x21, 0x0, 16)
{
/* Input is a key-value pair containing the info field data */
/* Input is a blob message containing the info field data */
message_port_register_in (pmt::mp ("info"));
d_addr_len = ax25_create_addr_field(d_addr_field, dest_addr, dest_ssid,
src_addr, src_ssid);
......@@ -69,15 +79,15 @@ namespace gr
/*
* Our virtual destructor.
*/
ax25_encoder_bf_impl::~ax25_encoder_bf_impl ()
ax25_encoder_mb_impl::~ax25_encoder_mb_impl ()
{
delete[] d_endoded_frame;
delete[] d_tmp_buf;
delete[] d_addr_field;
delete [] d_encoded_frame;
delete [] d_tmp_buf;
delete [] d_addr_field;
}
int
ax25_encoder_bf_impl::work (int noutput_items,
ax25_encoder_mb_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
......@@ -89,12 +99,14 @@ namespace gr
pmt::pmt_t msg;
ax25_encode_status_t status;
float *out = (float *) output_items[0];
uint8_t *out = (uint8_t *) output_items[0];
/* If all the frame samples have already be sent, wait for a new frame */
if (d_remaining == 0) {
boost::mutex::scoped_lock lock (d_mutex);
d_produced = 0;
d_prev_bit = 0x0;
d_lfsr.reset();
/* Block waiting from a new message from users */
msg = delete_head_blocking (pmt::mp ("info"));
......@@ -103,50 +115,52 @@ namespace gr
/* Prepare and encode the AX.25 frame */
len = ax25_prepare_frame (d_tmp_buf, info, info_len, AX25_I_FRAME,
d_addr_field, d_addr_len, 0, 1);
status = ax25_nrz_bit_stuffing(d_endoded_frame, &d_remaining, d_tmp_buf,
len);
if(status != AX25_ENC_OK){
LOG_ERROR("NRZ Encoding failed");
d_addr_field, d_addr_len, 0, 1,
d_preamble_len, d_postamble_len);
/* Perform bit stuffing */
status = ax25_bit_stuffing (d_encoded_frame, &d_remaining, d_tmp_buf,
len, d_preamble_len, d_postamble_len);
if (status != AX25_ENC_OK) {
LOG_ERROR ("AX.25 encoding failed");
d_remaining = 0;
return 0;
}
}
/* If this is the first part of the frame add the start of burst tag*/
if(d_produced == 0) {
add_sob(nitems_written(0));
}
max_avail = std::min(d_remaining, (size_t) noutput_items);
memcpy(out, d_endoded_frame + d_produced, max_avail * sizeof(float));
d_remaining -= max_avail;
d_produced += max_avail;
if(d_remaining == 0){
add_eob(nitems_written(0) + max_avail);
/*Perform scrambling if the user asked for it */
if(d_scramble){
for(i = 0; i < d_remaining; i++){
d_encoded_frame[i] = d_lfsr.next_bit_scramble(d_encoded_frame[i]);
}