From 10d4519bcbee5f1ed89c4cf4dbb0702ac7a044b8 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Mon, 11 Apr 2016 21:26:57 +0300 Subject: [PATCH] Implement the whitening and de-whitening process for the UPSAT The data whitening and de-whitening mechanism is implemented using lookup tables for fast processing times. The implementation is quite generic and modular supporting user defined polynomial masks and seeds. The lookup table is created during the initialization without any runtime overhead. --- grc/CMakeLists.txt | 3 +- grc/satnogs_whitening.xml | 38 +++++++++ include/satnogs/CMakeLists.txt | 3 +- include/satnogs/whitening.h | 57 +++++++++++++ lib/CMakeLists.txt | 3 +- lib/upsat_fsk_frame_acquisition_impl.cc | 25 ++++-- lib/upsat_fsk_frame_acquisition_impl.h | 2 + lib/upsat_fsk_frame_encoder_impl.cc | 13 ++- lib/upsat_fsk_frame_encoder_impl.h | 2 + lib/whitening.cc | 109 ++++++++++++++++++++++++ swig/satnogs_swig.i | 2 + 11 files changed, 248 insertions(+), 9 deletions(-) create mode 100644 grc/satnogs_whitening.xml create mode 100644 include/satnogs/whitening.h create mode 100644 lib/whitening.cc diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index c260c62..e76e60c 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -33,5 +33,6 @@ install(FILES satnogs_frame_encoder.xml satnogs_doppler_correction_cc.xml satnogs_upsat_fsk_frame_acquisition.xml - satnogs_upsat_fsk_frame_encoder.xml DESTINATION share/gnuradio/grc/blocks + satnogs_upsat_fsk_frame_encoder.xml + satnogs_whitening.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_whitening.xml b/grc/satnogs_whitening.xml new file mode 100644 index 0000000..66815b7 --- /dev/null +++ b/grc/satnogs_whitening.xml @@ -0,0 +1,38 @@ + + + whitening + satnogs_whitening + satnogs + import satnogs + satnogs.whitening($mask, $seed, $order) + + + ... + ... + ... + + + + + in + + + + + + out + + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 32e4a5d..802df56 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -46,5 +46,6 @@ install(FILES doppler_fit.h freq_drift.h upsat_fsk_frame_acquisition.h - upsat_fsk_frame_encoder.h DESTINATION include/satnogs + upsat_fsk_frame_encoder.h + whitening.h DESTINATION include/satnogs ) diff --git a/include/satnogs/whitening.h b/include/satnogs/whitening.h new file mode 100644 index 0000000..e68117f --- /dev/null +++ b/include/satnogs/whitening.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 . + */ + +#ifndef INCLUDED_SATNOGS_WHITENING_H +#define INCLUDED_SATNOGS_WHITENING_H + +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Performs data whitening and de-whitening + * + */ + class SATNOGS_API whitening + { + public: + whitening (uint32_t mask, uint32_t seed, uint32_t order); + ~whitening (); + + void + reset(); + + void scramble(uint8_t *out, const uint8_t *in, size_t len); + void descramble(uint8_t *out, const uint8_t *in, size_t len); + + private: + const size_t d_lut_len; + size_t d_lut_idx; + uint8_t *d_lut; + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_WHITENING_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d7e88bb..870bf06 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -44,7 +44,8 @@ list(APPEND satnogs_sources doppler_fit.cc freq_drift.cc upsat_fsk_frame_acquisition_impl.cc - upsat_fsk_frame_encoder_impl.cc ) + upsat_fsk_frame_encoder_impl.cc + whitening.cc ) set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE) if(NOT satnogs_sources) diff --git a/lib/upsat_fsk_frame_acquisition_impl.cc b/lib/upsat_fsk_frame_acquisition_impl.cc index bea3176..c150e1e 100644 --- a/lib/upsat_fsk_frame_acquisition_impl.cc +++ b/lib/upsat_fsk_frame_acquisition_impl.cc @@ -72,7 +72,8 @@ namespace gr d_shifting_byte (0x0), d_decoded_bytes (0), d_decoded_bits (0), - d_frame_len (0) + d_frame_len (0), + d_descrambler(0x21, 0x1FF, 9) { size_t i; message_port_register_out (pmt::mp ("pdu")); @@ -154,6 +155,7 @@ namespace gr upsat_fsk_frame_acquisition_impl::have_frame_len () { LOG_DEBUG("Enter frame len"); + d_descrambler.reset(); d_state = HAVE_FRAME_LEN; d_decoded_bytes = 0; d_decoded_bits = 0; @@ -243,10 +245,20 @@ namespace gr case HAVE_FRAME_LEN: d_decoded_bits++; if(d_decoded_bits == 8) { - /* Frame length field is needed for the CRC calculation */ - d_pdu[0] = d_shifting_byte; - /* CRC is not included in the frame length field, but we want it */ - d_frame_len = 1 + d_shifting_byte + sizeof(uint16_t); + + /* Length field has been whitened if the option is enabled */ + if(d_whitening){ + /* Frame length field is needed for the CRC calculation */ + d_descrambler.descramble(d_pdu, &d_shifting_byte, 1); + /* CRC is not included in the frame length field, but we want it */ + d_frame_len = 1 + d_pdu[0] + sizeof(uint16_t); + } + else{ + /* Frame length field is needed for the CRC calculation */ + d_pdu[0] = d_shifting_byte; + /* CRC is not included in the frame length field, but we want it */ + d_frame_len = 1 + d_shifting_byte + sizeof(uint16_t); + } have_payload(); } break; @@ -258,6 +270,9 @@ namespace gr d_decoded_bytes++; if (d_decoded_bytes == d_frame_len) { + if(d_whitening){ + d_descrambler.descramble(d_pdu+1, d_pdu+1, d_frame_len - 1); + } if(!d_check_crc){ message_port_pub ( pmt::mp ("pdu"), diff --git a/lib/upsat_fsk_frame_acquisition_impl.h b/lib/upsat_fsk_frame_acquisition_impl.h index ad8a1cb..750224e 100644 --- a/lib/upsat_fsk_frame_acquisition_impl.h +++ b/lib/upsat_fsk_frame_acquisition_impl.h @@ -23,6 +23,7 @@ #include #include +#include namespace gr { @@ -59,6 +60,7 @@ namespace gr size_t d_decoded_bytes; size_t d_decoded_bits; size_t d_frame_len; + whitening d_descrambler; uint8_t *d_pdu; inline void diff --git a/lib/upsat_fsk_frame_encoder_impl.cc b/lib/upsat_fsk_frame_encoder_impl.cc index 8fae92a..7b2e0f6 100644 --- a/lib/upsat_fsk_frame_encoder_impl.cc +++ b/lib/upsat_fsk_frame_encoder_impl.cc @@ -66,7 +66,8 @@ namespace gr d_max_pdu_len(d_preamble_len + d_sync_word_len + sizeof(uint8_t) + UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)), d_encoded(0), - d_pdu_len(0) + d_pdu_len(0), + d_scrambler(0x21, 0x1FF, 9) { /* Simplify the logic of the output samples handling */ set_output_multiple(8); @@ -181,6 +182,16 @@ namespace gr d_pdu_len += sizeof(uint16_t); } + /* + * Whitening is performed on all byes except preamble and SYNC fields + */ + if(d_whitening){ + d_scrambler.reset(); + d_scrambler.scramble (d_pdu + d_preamble_len + d_sync_word_len, + d_pdu + d_preamble_len + d_sync_word_len, + d_pdu_len + 1); + } + d_pdu_len += d_preamble_len + d_sync_word_len + 1; } diff --git a/lib/upsat_fsk_frame_encoder_impl.h b/lib/upsat_fsk_frame_encoder_impl.h index cffd0c6..0952e0d 100644 --- a/lib/upsat_fsk_frame_encoder_impl.h +++ b/lib/upsat_fsk_frame_encoder_impl.h @@ -22,6 +22,7 @@ #define INCLUDED_SATNOGS_UPSAT_FSK_FRAME_ENCODER_IMPL_H #include +#include namespace gr { @@ -42,6 +43,7 @@ namespace gr const size_t d_max_pdu_len; size_t d_encoded; size_t d_pdu_len; + whitening d_scrambler; uint8_t *d_pdu; inline void diff --git a/lib/whitening.cc b/lib/whitening.cc new file mode 100644 index 0000000..3c54afa --- /dev/null +++ b/lib/whitening.cc @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace gr { + namespace satnogs { + + /** + * 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::whitening (uint32_t mask, uint32_t seed, uint32_t order) : + d_lut_len (std::pow (2, order)), + d_lut_idx (0) + { + size_t i; + size_t j; + uint32_t cnt; + uint32_t shift_reg = seed; + + if (order > 32) { + throw std::invalid_argument ("The maximum allowed order is 32"); + } + + d_lut = new uint8_t[d_lut_len]; + + for (i = 0; i < d_lut_len; i++) { + d_lut[i] = shift_reg & 0xFF; + for (j = 0; j < 8; j++) { + cnt = bit_count (shift_reg & mask) % 2; + shift_reg = shift_reg >> 1; + shift_reg |= cnt << (order - 1); + } + } + } + + whitening::~whitening() + { + delete [] d_lut; + } + + /** + * Resets the scrambler (or the descrambler) to the initial stage and + * the initial seed. + */ + void + whitening::reset () + { + d_lut_idx = 0; + } + + /** + * Performs data scrambling + * @param out the output buffer + * @param in the input buffer + * @param len the number of the bytes to be scrambled + */ + void + whitening::scramble (uint8_t* out, const uint8_t* in, size_t len) + { + size_t i; + for(i = 0; i < len; i++){ + out[i] = in[i] ^ d_lut[ (d_lut_idx + i ) % d_lut_len]; + } + d_lut_idx = (d_lut_idx + len ) % d_lut_len; + } + + /** + * Performs data de-scrambling + * @param out the output buffer + * @param in the input buffer + * @param len the number of the bytes to be de-scrambled + */ + void + whitening::descramble (uint8_t* out, const uint8_t* in, size_t len) + { + scramble(out, in, len); + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index ebec1e7..9e1f567 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -27,6 +27,7 @@ #include "satnogs/frame_encoder.h" #include "satnogs/upsat_fsk_frame_acquisition.h" #include "satnogs/upsat_fsk_frame_encoder.h" +#include "satnogs/whitening.h" %} @@ -65,3 +66,4 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, doppler_correction_cc); GR_SWIG_BLOCK_MAGIC2(satnogs, upsat_fsk_frame_acquisition); %include "satnogs/upsat_fsk_frame_encoder.h" GR_SWIG_BLOCK_MAGIC2(satnogs, upsat_fsk_frame_encoder); +%include "satnogs/whitening.h"