Add LRPT decoding flowgraph

This commit is contained in:
Manolis Surligas 2018-08-09 19:29:47 +03:00
parent 854becb15d
commit 63218b157b
8 changed files with 238 additions and 124 deletions

View File

@ -17,11 +17,15 @@
<name>AMSAT FOX</name> <name>AMSAT FOX</name>
<block>satnogs_fox_telem_mm</block> <block>satnogs_fox_telem_mm</block>
</cat> </cat>
<cat>
<name>METOP</name>
<block>satnogs_lrpt_sync</block>
<block>satnogs_lrpt_decoder</block>
</cat>
</cat> </cat>
<block>satnogs_cw_matched_filter_ff</block> <block>satnogs_cw_matched_filter_ff</block>
<block>satnogs_morse_decoder</block> <block>satnogs_morse_decoder</block>
<block>satnogs_multi_format_msg_sink</block> <block>satnogs_multi_format_msg_sink</block>
<block>satnogs_lrpt_sync</block>
<block>satnogs_iq_sink</block> <block>satnogs_iq_sink</block>
<block>satnogs_ogg_encoder</block> <block>satnogs_ogg_encoder</block>
<block>satnogs_ogg_source</block> <block>satnogs_ogg_source</block>

View File

@ -23,12 +23,16 @@
#include <cstdint> #include <cstdint>
#include <cmath> #include <cmath>
#include <arpa/inet.h>
namespace gr namespace gr
{ {
namespace satnogs namespace satnogs
{ {
#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
/** /**
* Computes the Mean Absolute Percentage Error * Computes the Mean Absolute Percentage Error
* @param ref the reference value * @param ref the reference value

View File

@ -41,8 +41,10 @@ namespace gr
void void
reset(); reset();
void scramble(uint8_t *out, const uint8_t *in, size_t len); void scramble(uint8_t *out, const uint8_t *in, size_t len,
void descramble(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,
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,

View File

@ -25,6 +25,9 @@
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include "lrpt_decoder_impl.h" #include "lrpt_decoder_impl.h"
#include <satnogs/log.h> #include <satnogs/log.h>
#include <satnogs/utils.h>
extern "C" { extern "C" {
#include <fec.h> #include <fec.h>
} }
@ -47,11 +50,18 @@ lrpt_decoder_impl::lrpt_decoder_impl()
: gr::block("lrpt_decoder", : gr::block("lrpt_decoder",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)), gr::io_signature::make(0, 0, 0)),
d_cadu_len(1020 + 4), /*
d_coded_cadu_len(1020 * 2 + 4*2), * Metop violates the standard as many times as possible...
d_conv_deinterl(36, 2048) * The frame should contain 128 RS check symbols at the end.
* For some unknown reasons, it seems that the RS encoding is not performed.
* Thus, they dropped the check symbols at the end of the frame.
*/
d_cadu_len(1020 + 4 - 128),
d_coded_cadu_len(1020 * 2 + 4*2 - 128 * 2),
d_mpdu_max_len(59400),
d_scrambler(0x2A9, 0xFF, 7),
d_have_mpdu(false)
{ {
message_port_register_in(pmt::mp("cadu")); message_port_register_in(pmt::mp("cadu"));
message_port_register_out(pmt::mp("frame")); message_port_register_out(pmt::mp("frame"));
@ -63,11 +73,13 @@ lrpt_decoder_impl::lrpt_decoder_impl()
if(!d_vt) { if(!d_vt) {
throw std::runtime_error("lrpt_decoder: Failed to init Viterbi decoder"); throw std::runtime_error("lrpt_decoder: Failed to init Viterbi decoder");
} }
int polys[2] = {0x79, 0x5b};
int polys[2] = {0x4f, 0x6d};
set_viterbi27_polynomial(polys); set_viterbi27_polynomial(polys);
d_cadu = new uint8_t[d_cadu_len]; d_cadu = new uint8_t[d_cadu_len];
d_coded_cadu_syms = new uint8_t[d_coded_cadu_len * 8]; d_coded_cadu_syms = new uint8_t[d_coded_cadu_len * 8];
d_mpdu = new uint8_t[d_mpdu_max_len];
} }
@ -79,6 +91,7 @@ lrpt_decoder_impl::~lrpt_decoder_impl ()
delete [] d_cadu; delete [] d_cadu;
delete [] d_coded_cadu_syms; delete [] d_coded_cadu_syms;
delete [] d_mpdu;
} }
void void
@ -93,21 +106,68 @@ lrpt_decoder_impl::decode (pmt::pmt_t m)
init_viterbi27(d_vt, 0); init_viterbi27(d_vt, 0);
for(size_t i = 0; i < d_coded_cadu_len; i++) { for(size_t i = 0; i < d_coded_cadu_len; i++) {
d_coded_cadu_syms[i * 8] = ~(255 + (coded_cadu[i] >> 7)); d_coded_cadu_syms[i * 8] = 0xFF * (coded_cadu[i] >> 7);
d_coded_cadu_syms[i * 8 + 1] = ~(255 + (coded_cadu[i] >> 6) & 0x1); d_coded_cadu_syms[i * 8 + 1] = 0xFF * ((coded_cadu[i] >> 6) & 0x1);
d_coded_cadu_syms[i * 8 + 2] = ~(255 + (coded_cadu[i] >> 5) & 0x1); d_coded_cadu_syms[i * 8 + 2] = 0xFF * ((coded_cadu[i] >> 5) & 0x1);
d_coded_cadu_syms[i * 8 + 3] = ~(255 + (coded_cadu[i] >> 4) & 0x1); d_coded_cadu_syms[i * 8 + 3] = 0xFF * ((coded_cadu[i] >> 4) & 0x1);
d_coded_cadu_syms[i * 8 + 4] = ~(255 + (coded_cadu[i] >> 3) & 0x1); d_coded_cadu_syms[i * 8 + 4] = 0xFF * ((coded_cadu[i] >> 3) & 0x1);
d_coded_cadu_syms[i * 8 + 5] = ~(255 + (coded_cadu[i] >> 2) & 0x1); d_coded_cadu_syms[i * 8 + 5] = 0xFF * ((coded_cadu[i] >> 2) & 0x1);
d_coded_cadu_syms[i * 8 + 6] = ~(255 + (coded_cadu[i] >> 1) & 0x1); d_coded_cadu_syms[i * 8 + 6] = 0xFF * ((coded_cadu[i] >> 1) & 0x1);
d_coded_cadu_syms[i * 8 + 7] = ~(255 + (coded_cadu[i] & 0x1)); d_coded_cadu_syms[i * 8 + 7] = 0xFF * ((coded_cadu[i] & 0x1));
} }
/* Convolutional decoding */
update_viterbi27_blk(d_vt, d_coded_cadu_syms, d_cadu_len * 8); update_viterbi27_blk(d_vt, d_coded_cadu_syms, d_cadu_len * 8);
chainback_viterbi27(d_vt, d_cadu, d_cadu_len * 8, 0); chainback_viterbi27(d_vt, d_cadu, d_cadu_len * 8, 0);
message_port_pub(pmt::mp("frame"), pmt::make_blob(d_cadu, d_cadu_len));
/* Descrambling */
d_scrambler.reset();
d_scrambler.descramble(d_cadu + 4, d_cadu + 4, d_cadu_len - 4, true);
decode_ccsds_packet(d_cadu + 4);
} }
void
lrpt_decoder_impl::decode_ccsds_packet(const uint8_t *cvcdu)
{
/* Check first the VCDU version and if encryption is off */
if( (cvcdu[0] >> 6) != 0x1) {
return;
}
if(cvcdu[6] != 0x0 || cvcdu[7] != 0x0) {
return;
}
/* Check if the VCDU contans data */
//if((cvcdu[8] >> 3) != 0x0 && (cvcdu[8] >> 3) != 0x1f) {
// return;
//}
const uint8_t *mpdu = cvcdu + 10;
/* Check CCSDS packet version and type */
//if( (mpdu[0] >> 5) != 0x0) {
// return;
// }
uint32_t vcdu_seq = 0;
vcdu_seq = cvcdu[2];
vcdu_seq = (vcdu_seq << 8) | cvcdu[3];
vcdu_seq = (vcdu_seq << 8) | cvcdu[4];
uint16_t hdr_ptr = 0;
hdr_ptr = cvcdu[8] & 0x7;
hdr_ptr = (hdr_ptr << 8) | cvcdu[9];
/* Try to find the start of a MPDU */
if(!d_have_mpdu) {
if(hdr_ptr != 0) {
return;
}
d_have_mpdu = true;
}
message_port_pub(pmt::mp("frame"), pmt::make_blob(cvcdu, d_cadu_len - 4));
}
} /* namespace satnogs */ } /* namespace satnogs */
} /* namespace gr */ } /* namespace gr */

View File

@ -23,6 +23,7 @@
#include <satnogs/lrpt_decoder.h> #include <satnogs/lrpt_decoder.h>
#include <satnogs/convolutional_deinterleaver.h> #include <satnogs/convolutional_deinterleaver.h>
#include <satnogs/whitening.h>
namespace gr namespace gr
{ {
@ -39,13 +40,20 @@ public:
private: private:
const size_t d_cadu_len; const size_t d_cadu_len;
const size_t d_coded_cadu_len; const size_t d_coded_cadu_len;
convolutional_deinterleaver d_conv_deinterl; const size_t d_mpdu_max_len;
whitening d_scrambler;
bool d_have_mpdu;
uint8_t *d_coded_cadu_syms; uint8_t *d_coded_cadu_syms;
uint8_t *d_cadu; uint8_t *d_cadu;
uint8_t *d_mpdu;
void *d_vt; void *d_vt;
void void
decode(pmt::pmt_t m); decode(pmt::pmt_t m);
void
decode_ccsds_packet(const uint8_t *cvcdu);
}; };
} // namespace satnogs } // namespace satnogs

View File

@ -58,12 +58,18 @@ lrpt_sync_impl::lrpt_sync_impl (size_t threshold) :
*/ */
d_window((72 + 8)/2), d_window((72 + 8)/2),
/* Each CADU has the 4 byte ASM and a VCDU of 1020 bytes*/ /* Each CADU has the 4 byte ASM and a VCDU of 1020 bytes*/
d_coded_cadu_len(1020 * 2 + 4*2), /*
* NOTE:
* Metop violates the standard as many times as possible...
* The frame should contain 128 RS check symbols at the end.
* For some unknown reasons, it seems that the RS encoding is not performed.
* Thus, they dropped the check symbols at the end of the frame.
*/
d_coded_cadu_len(1020 * 2 + 4*2 - 128 * 2),
d_frame_sync(false), d_frame_sync(false),
d_received(0), d_received(0),
d_rotate(1, 0), d_rotate(1.0, 0.0),
d_qpsk(digital::constellation_qpsk::make()), d_qpsk(digital::constellation_qpsk::make()),
d_conv_deinter(36, 2048),
d_shift_reg0(0x0), d_shift_reg0(0x0),
d_shift_reg1(0x0), d_shift_reg1(0x0),
d_shift_reg2(0x0), d_shift_reg2(0x0),
@ -72,25 +78,29 @@ lrpt_sync_impl::lrpt_sync_impl (size_t threshold) :
set_output_multiple(d_window); set_output_multiple(d_window);
const int alignment_multiple = volk_get_alignment () / sizeof(gr_complex); const int alignment_multiple = volk_get_alignment () / sizeof(gr_complex);
set_alignment (std::max (1, alignment_multiple)); set_alignment (std::max (1, alignment_multiple));
d_rotate_pi2 = (gr_complex *)volk_malloc(d_window, volk_get_alignment ()); d_rotate_pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex),
volk_get_alignment ());
if(!d_rotate_pi2) { if(!d_rotate_pi2) {
throw std::runtime_error("lrpt_sync: Could not allocate memory"); throw std::runtime_error("lrpt_sync: Could not allocate memory");
} }
d_rotate_2pi2 = (gr_complex *)volk_malloc(d_window, volk_get_alignment ()); d_rotate_2pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex),
volk_get_alignment ());
if(!d_rotate_2pi2) { if(!d_rotate_2pi2) {
volk_free(d_rotate_pi2); volk_free(d_rotate_pi2);
throw std::runtime_error("lrpt_sync: Could not allocate memory"); throw std::runtime_error("lrpt_sync: Could not allocate memory");
} }
d_rotate_3pi2 = (gr_complex *)volk_malloc(d_window, volk_get_alignment ()); d_rotate_3pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex),
volk_get_alignment ());
if(!d_rotate_3pi2) { if(!d_rotate_3pi2) {
volk_free(d_rotate_pi2); volk_free(d_rotate_pi2);
volk_free(d_rotate_2pi2); volk_free(d_rotate_2pi2);
throw std::runtime_error("lrpt_sync: Could not allocate memory"); throw std::runtime_error("lrpt_sync: Could not allocate memory");
} }
d_corrected = (gr_complex *)volk_malloc(d_window, volk_get_alignment ()); d_corrected = (gr_complex *)volk_malloc(d_window * sizeof(gr_complex),
volk_get_alignment ());
if(!d_corrected) { if(!d_corrected) {
volk_free(d_rotate_pi2); volk_free(d_rotate_pi2);
volk_free(d_rotate_2pi2); volk_free(d_rotate_2pi2);
@ -98,7 +108,7 @@ lrpt_sync_impl::lrpt_sync_impl (size_t threshold) :
throw std::runtime_error("lrpt_sync: Could not allocate memory"); throw std::runtime_error("lrpt_sync: Could not allocate memory");
} }
uint64_t asm_coded = reverse_uint64_bytes(d_asm_coded); uint64_t asm_coded = htonll(d_asm_coded);
d_coded_cadu = new uint8_t[d_coded_cadu_len]; d_coded_cadu = new uint8_t[d_coded_cadu_len];
memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t)); memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t));
d_received = sizeof(uint64_t); d_received = sizeof(uint64_t);
@ -133,11 +143,11 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items)
int multiple = noutput_items / d_window; int multiple = noutput_items / d_window;
for(int i = 0; i < multiple; i++) { for(int i = 0; i < multiple; i++) {
volk_32fc_s32fc_multiply_32fc(d_rotate_pi2, in + i * d_window, volk_32fc_s32fc_multiply_32fc(d_rotate_pi2, in + i * d_window,
gr_complex(0, 1), d_window); gr_complex(0.0, 1.0), d_window);
volk_32fc_s32fc_multiply_32fc(d_rotate_2pi2, in + i * d_window, volk_32fc_s32fc_multiply_32fc(d_rotate_2pi2, in + i * d_window,
gr_complex(-1, 0), d_window); gr_complex(-1.0, 0.0), d_window);
volk_32fc_s32fc_multiply_32fc(d_rotate_3pi2, in + i * d_window, volk_32fc_s32fc_multiply_32fc(d_rotate_3pi2, in + i * d_window,
gr_complex(0, -1), d_window); gr_complex(0.0, -1.0), d_window);
/* /*
* Search for the sync pattern, rotating the QPSK constellation on * Search for the sync pattern, rotating the QPSK constellation on
* all possible positions * all possible positions
@ -147,9 +157,11 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items)
//bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1);
d_shift_reg0 = (d_shift_reg0 << 2) | bits; d_shift_reg0 = (d_shift_reg0 << 2) | bits;
if(found_sync(d_shift_reg0)) { if(found_sync(d_shift_reg0)) {
d_rotate = gr_complex(1.0, 0); d_rotate = gr_complex(1.0, 0.0);
d_frame_sync = true; d_frame_sync = true;
return i * d_window + j; uint64_t asm_coded = htonll(d_shift_reg0);
memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t));
return i * d_window + j + 1;
} }
bits = d_qpsk->decision_maker(d_rotate_pi2 + j); bits = d_qpsk->decision_maker(d_rotate_pi2 + j);
@ -158,16 +170,20 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items)
if(found_sync(d_shift_reg1)) { if(found_sync(d_shift_reg1)) {
d_rotate = gr_complex(0.0, 1.0); d_rotate = gr_complex(0.0, 1.0);
d_frame_sync = true; d_frame_sync = true;
return i * d_window + j; uint64_t asm_coded = htonll(d_shift_reg1);
memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t));
return i * d_window + j + 1;
} }
bits = d_qpsk->decision_maker(d_rotate_2pi2 + j); bits = d_qpsk->decision_maker(d_rotate_2pi2 + j);
//bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1);
d_shift_reg2 = (d_shift_reg2 << 2) | bits; d_shift_reg2 = (d_shift_reg2 << 2) | bits;
if(found_sync(d_shift_reg2)) { if(found_sync(d_shift_reg2)) {
d_rotate = gr_complex(-1.0, 0); d_rotate = gr_complex(-1.0, 0.0);
d_frame_sync = true; d_frame_sync = true;
return i * d_window + j; uint64_t asm_coded = htonll(d_shift_reg2);
memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t));
return i * d_window + j + 1;
} }
bits = d_qpsk->decision_maker(d_rotate_3pi2 + j); bits = d_qpsk->decision_maker(d_rotate_3pi2 + j);
@ -176,7 +192,9 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items)
if(found_sync(d_shift_reg3)) { if(found_sync(d_shift_reg3)) {
d_rotate = gr_complex(0.0, -1.0); d_rotate = gr_complex(0.0, -1.0);
d_frame_sync = true; d_frame_sync = true;
return i * d_window + j; uint64_t asm_coded = htonll(d_shift_reg3);
memcpy(d_coded_cadu, &asm_coded, sizeof(uint64_t));
return i * d_window + j + 1;
} }
} }
} }
@ -200,7 +218,6 @@ lrpt_sync_impl::work_sync(const gr_complex *in, int noutput_items)
d_coded_cadu[d_received++] = b; d_coded_cadu[d_received++] = b;
if(d_received == d_coded_cadu_len) { if(d_received == d_coded_cadu_len) {
LOG_ERROR("frame");
d_received = sizeof(uint64_t); d_received = sizeof(uint64_t);
d_frame_sync = false; d_frame_sync = false;
message_port_pub (pmt::mp ("cadu"), message_port_pub (pmt::mp ("cadu"),

View File

@ -44,7 +44,7 @@ public:
private: private:
const size_t d_thresh; const size_t d_thresh;
const uint64_t d_asm_coded; const uint64_t d_asm_coded;
const uint64_t d_asm_coded_len; const size_t d_asm_coded_len;
const uint64_t d_asm_coded_mask; const uint64_t d_asm_coded_mask;
const int d_window; const int d_window;
const size_t d_coded_cadu_len; const size_t d_coded_cadu_len;
@ -52,7 +52,6 @@ private:
size_t d_received; size_t d_received;
gr_complex d_rotate; gr_complex d_rotate;
digital::constellation_qpsk::sptr d_qpsk; digital::constellation_qpsk::sptr d_qpsk;
convolutional_deinterleaver d_conv_deinter;
uint64_t d_shift_reg0; uint64_t d_shift_reg0;
uint64_t d_shift_reg1; uint64_t d_shift_reg1;
uint64_t d_shift_reg2; uint64_t d_shift_reg2;

View File

@ -26,97 +26,117 @@
#include <satnogs/whitening.h> #include <satnogs/whitening.h>
#include <satnogs/utils.h> #include <satnogs/utils.h>
namespace gr { namespace gr
namespace satnogs { {
namespace satnogs
{
/** /**
* Data whitening and de-whitening class * Data whitening and de-whitening class
* @param mask the polynomial mask * @param mask the polynomial mask
* @param seed the initial seed * @param seed the initial seed
* @param order the order of the shift register. This is equal to the * @param order the order of the shift register. This is equal to the
* 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)
{ {
} }
/** /**
* Resets the scrambler (or the descrambler) to the initial stage and * Resets the scrambler (or the descrambler) to the initial stage and
* the initial seed. * the initial seed.
*/ */
void void
whitening::reset () whitening::reset ()
{ {
d_lfsr.reset(); d_lfsr.reset ();
} }
/** /**
* Performs data scrambling * Performs data scrambling
* @param out the output buffer * @param out the output buffer
* @param in the input buffer * @param in the input buffer
* @param len the number of the bytes to be scrambled * @param len the number of the bytes to be scrambled
* @param msb if set to true, the descrambler starts from the msb
*/ */
void void
whitening::scramble (uint8_t* out, const uint8_t* in, size_t len) whitening::scramble (uint8_t* out, const uint8_t* in, size_t len, bool msb)
{ {
size_t i; size_t i;
uint8_t b; uint8_t b;
for(i = 0; i < len; i++){ if(msb) {
b = d_lfsr.next_bit(); for (i = 0; i < len; i++) {
b |= d_lfsr.next_bit() << 1; b = d_lfsr.next_bit () << 7;
b |= d_lfsr.next_bit() << 2; b |= d_lfsr.next_bit () << 6;
b |= d_lfsr.next_bit() << 3; b |= d_lfsr.next_bit () << 5;
b |= d_lfsr.next_bit() << 4; b |= d_lfsr.next_bit () << 4;
b |= d_lfsr.next_bit() << 5; b |= d_lfsr.next_bit () << 3;
b |= d_lfsr.next_bit() << 6; b |= d_lfsr.next_bit () << 2;
b |= d_lfsr.next_bit() << 7; b |= d_lfsr.next_bit () << 1;
b |= d_lfsr.next_bit ();
out[i] = in[i] ^ b; out[i] = in[i] ^ b;
} }
} }
else{
for (i = 0; i < len; i++) {
b = d_lfsr.next_bit ();
b |= d_lfsr.next_bit () << 1;
b |= d_lfsr.next_bit () << 2;
b |= d_lfsr.next_bit () << 3;
b |= d_lfsr.next_bit () << 4;
b |= d_lfsr.next_bit () << 5;
b |= d_lfsr.next_bit () << 6;
b |= d_lfsr.next_bit () << 7;
out[i] = in[i] ^ b;
}
}
}
/** /**
* Performs data de-scrambling * Performs data de-scrambling
* @param out the output buffer * @param out the output buffer
* @param in the input buffer * @param in the input buffer
* @param len the number of the bytes to be de-scrambled * @param len the number of the bytes to be de-scrambled
* @param msb if set to true, the descrambler starts from the msb
*/ */
void void
whitening::descramble (uint8_t* out, const uint8_t* in, size_t len) whitening::descramble (uint8_t* out, const uint8_t* in, size_t len,
{ bool msb)
scramble(out, in, len); {
} scramble (out, in, len, msb);
}
/** /**
* Performs data scrambling. The input and output buffer * Performs data scrambling. The input and output buffer
* contain one bit per byte * contain one bit per byte
* @param out the output buffer * @param out the output buffer
* @param in the input buffer * @param in the input buffer
* @param bits_num the number of bits to be scrambled * @param bits_num the number of bits to be scrambled
*/ */
void void
whitening::scramble_one_bit_per_byte (uint8_t* out, const uint8_t* in, whitening::scramble_one_bit_per_byte (uint8_t* out, const uint8_t* in,
size_t bits_num) size_t bits_num)
{ {
size_t i; size_t i;
for(i = 0; i < bits_num; i++){ for (i = 0; i < bits_num; i++) {
out[i] = in[i] ^ d_lfsr.next_bit(); out[i] = in[i] ^ d_lfsr.next_bit ();
}
} }
}
/** /**
* Performs data descrambling. The input and output buffer * Performs data descrambling. The input and output buffer
* contain one bit per byte * contain one bit per byte
* @param out the output buffer * @param out the output buffer
* @param in the input buffer * @param in the input buffer
* @param bits_num the number of bits to be descrambled * @param bits_num the number of bits to be descrambled
*/ */
void void
whitening::descramble_one_bit_per_byte (uint8_t* out, const uint8_t* in, whitening::descramble_one_bit_per_byte (uint8_t* out, const uint8_t* in,
size_t bits_num) size_t bits_num)
{ {
scramble_one_bit_per_byte(out, in, bits_num); scramble_one_bit_per_byte (out, in, bits_num);
} }
} /* namespace satnogs */ } /* namespace satnogs */
} /* namespace gr */ } /* namespace gr */