diff --git a/README.md b/README.md index f7f1f46..8995361 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,35 @@ Before submitting a new merge request, rebase the `master` branch and confirm that the automated CI tests have successfully completed for all platforms mandated by the `.gitlab-ci.yml` recipe. +### Coding style +For the C++ code, `gr-satnogs` uses a slightly modified version of the +**Stroustrup** style, which is a nicer adaptation of the well known K&R style. +In addition, we decided to decrease the indentation from 4 to 2 spaces. +This choice was made mainly to avoid braking statements with long namespaces. +We also found ourselves, that with smaller indentation we use more descriptive +variable names, avoiding frustrating abbreviations without phoenixes etc. + +At the root directory of the project there is the `astyle` options +file `.astylerc` containing the proper configuration. +Developers can import this configuration to their favorite editor. +In addition the `hooks/pre-commit` file contains a Git hook, +that can be used to perform before every commit, code style formatting +with `astyle` and the `.astylerc` parameters. +To enable this hook developers should copy the hook at their `.git/hooks` +directory. +Failing to comply with the coding style described by the `.astylerc` +will result to failure of the automated tests running on our CI services. +So make sure that you either import on your editor the coding style rules +or use the `pre-commit` Git hook. + + +Regarding the naming of files and variables, we use the underscore naming +convention (`do_this`) instead of camel cases (`DoNotDoThis`). +Exception to this rule is the CMake module filenames. In addition, +all private variables of a C++ class, should start with the prefix +`d_` allowing the developers to spot easily private members of the object. + + ### Adding a new Satellite Demodulator Demodulators are responsible for filtering, resampling and demodulating an analog signal and converting it into suitable form, for a decoder to be able @@ -125,15 +154,16 @@ The `satnogs::decoder` class, is a virtual class providing a generic API that every derived decoder class should implement. The core of this class is the -``` -decoder_status_t decode (const void *in, int len) +```cpp +decoder_status_t +decode(const void *in, int len) ``` method. This method accepts an input buffer `in`. The type of the items depends on the implementation. It also takes the `len` argument specifying the number of items available in the `in` buffer. The method returns a `decoder_status_t` class object. -``` +```cpp class decoder_status { public: @@ -164,32 +194,6 @@ decoded and its data are available on the `data` field. information regarding it, using the `gr-satnogs` metadata format. More about them in the [Metadata](#metadata) section -### Coding style -For the C++ code, `gr-satnogs` uses a slightly modified version of the -**Stroustrup** style, which is a nicer adaptation of the well known K&R style. -In addition, we decided to decrease the indentation from 4 to 2 spaces. -This choice was made mainly to avoid braking statements with long namespaces. -We also found ourselves, that with smaller indentation we use more descriptive -variable names, avoiding frustrating abbreviations without phoenixes etc. - -At the root directory of the project there is the `astyle` options -file `.astylerc` containing the proper configuration. -Developers can import this configuration to their favorite editor. -In addition the `hooks/pre-commit` file contains a Git hook, -that can be used to perform before every commit, code style formatting -with `astyle` and the `.astylerc` parameters. -To enable this hook developers should copy the hook at their `.git/hooks` -directory. -Failing to comply with the coding style described by the `.astylerc` -will result to failure of the automated tests running on our CI services. -So make sure that you either import on your editor the coding style rules -or use the `pre-commit` Git hook. - - -Regarding the naming of files and variables, we use the underscore naming convention (`do_this`) instead of -camel cases (`DoNotDoThis`). -Exception to this rule is the CMake module filenames. In addition, all private variables of a C++ class, should start with the prefix `d_` allowing the developers to spot easily private members of the object. - ### Metadata Each decoder generates a `pmt::pmt_t` dictionary containing the decoded data and @@ -216,7 +220,7 @@ metadata::keys()` static method which returns a list with the available metadata keys. This method is also available in Python through the Swig interface. For example: -``` +```python $ python >>> import satnogs >>> satnogs.metadata.keys() @@ -230,7 +234,24 @@ containing the raw bytes of the JSON string, which then can be passed to a UDP sink targeting the `satnogs-client`. The `json_converter` block accepts also a string that may be used to inject an arbitrary number of additional information under the `extra` JSON field. -Of course, this string should be in a JSON valid format. +Of course, this string should be in a JSON valid format. + +For example, such a JSON string with information on the extra field could be like + +```json +{ + "corrected_bits" : 0, + "extra" : + { + "x" : 3, + "y" : "test" + }, + "pdu" : "igAg7nRAOCAniUMAtIoAAAAAAAAAAAAAAABNJ4kfAFD4wwAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "symbol_erasures" : 0, + "time" : "2019-09-11T15:39:13.514138Z" +} +``` + ### Release Policy The `gr-satnogs` OOT module uses the `major.api-compatibility.minor` diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index c97d302..0c42bea 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -50,6 +50,7 @@ list(APPEND enabled_blocks satnogs_ogg_source.xml satnogs_noaa_apt_sink.xml satnogs_whitening.xml + satnogs_ieee802_15_4_variant_decoder.xml ) if(${INCLUDE_DEBUG_BLOCKS}) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index 71e9748..19a4346 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -4,6 +4,7 @@ Decoders variable_ax25_decoder variable_amsat_duv_decoder + variable_ieee802_15_4_variant_decoder Satellites diff --git a/grc/satnogs_ieee802_15_4_variant_decoder.xml b/grc/satnogs_ieee802_15_4_variant_decoder.xml new file mode 100644 index 0000000..f3455cd --- /dev/null +++ b/grc/satnogs_ieee802_15_4_variant_decoder.xml @@ -0,0 +1,80 @@ + + + IEEE 802.15.4 Decoder Definition + variable_ieee802_15_4_variant_decoder + import satnogs + self.$(id) = $(id) = satnogs.ieee802_15_4_variant_decoder_make($preamble, $preamble_thrsh, $sync_word, $sync_thrsh, $crc, $whitening, $var_len, $frame_len) + satnogs.ieee802_15_4_variant_decoder_make($preamble, $preamble_thrsh, $sync_word, $sync_thrsh, $crc, $whitening, $var_len, $frame_len) + + + Ignore Me + value + 'ok' + raw + all + + + + Variable Length + var_len + enum + + + + + + Frame Preamble + preamble + [0x55, 0x55, 0x55, 0x55, 0x55] + raw + + + + Preamble Threshold + preamble_thrsh + 5 + int + + + + Synchronization Word + sync_word + [0x31, 0xe5] + raw + + + + Synchronization Word Threshold + sync_thrsh + 3 + int + + + + Maximum Frame Length + frame_len + 254 + int + + + + CRC + crc + None + raw + + + + Whitening + whitening + None + raw + + + \ No newline at end of file diff --git a/include/satnogs/crc.h b/include/satnogs/crc.h index d063f4e..2f71cd0 100644 --- a/include/satnogs/crc.h +++ b/include/satnogs/crc.h @@ -33,15 +33,12 @@ namespace satnogs { class SATNOGS_API crc { public: typedef enum crc_type { - PDU = 0, - CRC_VALID, - FREQ_OFFSET, - CORRECTED_BITS, - TIME, - SAMPLE_START, - SAMPLE_CNT, - SYMBOL_ERASURES, - KEYS_NUM + CRC_NONE = 0, + CRC16_CCITT, + CRC16_CCITT_REVERSED, + CRC16_AX25, + CRC16_IBM, + CRC_METHODS_NUM } crc_t; static uint16_t @@ -56,6 +53,9 @@ public: static uint16_t crc16_ibm(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]; diff --git a/include/satnogs/decoder.h b/include/satnogs/decoder.h index ea705b8..c0c01d6 100644 --- a/include/satnogs/decoder.h +++ b/include/satnogs/decoder.h @@ -101,6 +101,9 @@ public: virtual void reset() = 0; + virtual size_t + input_multiple() const; + size_t max_frame_len() const; diff --git a/include/satnogs/ieee802_15_4_variant_decoder.h b/include/satnogs/ieee802_15_4_variant_decoder.h index a0665e0..99778b6 100644 --- a/include/satnogs/ieee802_15_4_variant_decoder.h +++ b/include/satnogs/ieee802_15_4_variant_decoder.h @@ -22,8 +22,11 @@ #define INCLUDED_SATNOGS_IEEE802_15_4_VARIANT_DECODER_H #include +#include #include #include +#include + namespace gr { namespace satnogs { @@ -38,15 +41,114 @@ namespace satnogs { * scheme. * */ -class SATNOGS_API ieee802_15_4_variant_decoder { +class SATNOGS_API ieee802_15_4_variant_decoder : public decoder { public: + + /** + * + * @param preamble the preamble should be a repeated word. Note that due to AGC + * settling, the receiver may not receive the whole preamble. If the preamble + * is indeed a repeated pattern, a portion of it can be given as parameter. + * The block should be able to deal with this. However, a quite small subset + * may lead to a larger number of false alarms + * + * @param preamble_threshold the maximum number of bits that are + * allowed to be wrong at the preamble + * + * @param sync the synchronization work following the preamble + * + * @param sync_threshold the maximum number of bits that are + * allowed to be wrong at the synchronization word + * + * @param crc the CRC scheme to use + * + * @param descrambler if set, data will be first descrambled by this descrambling + * method + * + * @param var_len if set to true, variable length decoding is used. Otherwise, + * the \p max_len parameter indicates the fixed frame size + * + * @param max_len the maximum allowed decode-able frame length + * + * @return shared pointer of the decoder + */ + static decoder::decoder_sptr + make(const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + crc::crc_t crc, + whitening::whitening_sptr descrambler, bool var_len = true, + size_t max_len = 1024); + ieee802_15_4_variant_decoder(const std::vector &preamble, size_t preamble_threshold, const std::vector &sync, + size_t sync_threshold, crc::crc_t crc, - whitening::whitening_sptr descrambler); + whitening::whitening_sptr descrambler, + bool var_len = true, + size_t max_len = 1024); ~ieee802_15_4_variant_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_GENERIC_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_var_len; + size_t d_len; + size_t d_length_field_len; + decoding_state_t d_state; + size_t d_cnt; + uint8_t *d_pdu; + + decoder_status_t + decode_var_len(const void *in, int len); + + decoder_status_t + decode_const_len(const void *in, int len); + + 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); + + void + decode_payload(decoder_status_t &status, const uint8_t *in, int len); + + bool + check_crc(); + }; } // namespace satnogs diff --git a/lib/crc.cc b/lib/crc.cc index 4de3ae2..f4eba94 100644 --- a/lib/crc.cc +++ b/lib/crc.cc @@ -149,6 +149,27 @@ crc::crc16_ibm(const uint8_t *data, size_t len) return crc; } +/** + * + * @param t the CRC method + * @return the size of the specified CRC in bytes + */ +size_t +crc::crc_size(crc_t t) +{ + switch (t) { + case CRC_NONE: + return 0; + case CRC16_CCITT: + case CRC16_CCITT_REVERSED: + case CRC16_AX25: + case CRC16_IBM: + return sizeof(uint16_t); + default: + throw std::invalid_argument("crc: Invalid CRC method"); + } +} + } /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/decoder.cc b/lib/decoder.cc index 5099070..fa690af 100644 --- a/lib/decoder.cc +++ b/lib/decoder.cc @@ -55,6 +55,22 @@ decoder::~decoder() { } +/** + * By default, the number of input items can be arbitrary (multiple of 1). + * Decoders that require the number of input items to be a multiple of a + * specific number, should override this method. + * + * The frame_decoder block, will use the number returned from this method + * to properly alter the behavior of the GNU Radio scheduler + * + * @return the number that input items should be multiple + */ +size_t +decoder::input_multiple() const +{ + return 1; +} + /** * * @return the maximum allowed frame length diff --git a/lib/frame_decoder_impl.cc b/lib/frame_decoder_impl.cc index a1a5544..d023858 100644 --- a/lib/frame_decoder_impl.cc +++ b/lib/frame_decoder_impl.cc @@ -50,6 +50,14 @@ frame_decoder_impl::frame_decoder_impl(decoder::decoder_sptr decoder_object, "frame_decoder: Size mismatch between the block input and the decoder"); } + /* + * Each decoder implementing the generic decoder API may have special + * requirements on the number of input items. If not, by default this will + * set a multiple of 1 item, which corresponds to an arbitrary number of + * samples + */ + set_output_multiple(d_decoder->input_multiple()); + message_port_register_in(pmt::mp("reset")); message_port_register_out(pmt::mp("out")); diff --git a/lib/ieee802_15_4_variant_decoder.cc b/lib/ieee802_15_4_variant_decoder.cc index d3d7379..c7fa7ee 100644 --- a/lib/ieee802_15_4_variant_decoder.cc +++ b/lib/ieee802_15_4_variant_decoder.cc @@ -23,21 +23,342 @@ #endif #include +#include #include +#include + +#include namespace gr { namespace satnogs { -ieee802_15_4_variant_decoder::ieee802_15_4_variant_decoder( - const std::vector &preamble, size_t preamble_threshold, - const std::vector &sync, crc::crc_t crc, - whitening::whitening_sptr descrambler) +decoder::decoder_sptr +ieee802_15_4_variant_decoder::make(const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + crc::crc_t crc, + whitening::whitening_sptr descrambler, + bool var_len, + size_t max_len) { + return decoder::decoder_sptr( + new ieee802_15_4_variant_decoder(preamble, preamble_threshold, + sync, sync_threshold, crc, + descrambler, var_len, max_len)); +} + +ieee802_15_4_variant_decoder::ieee802_15_4_variant_decoder( + const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + crc::crc_t crc, + whitening::whitening_sptr descrambler, + bool var_len, size_t max_len) : + decoder(sizeof(uint8_t), max_len), + 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_descrambler(descrambler), + d_crc(crc), + d_var_len(var_len), + d_len(max_len + crc::crc_size(crc)), + d_length_field_len(0), + d_state(SEARCHING), + d_cnt(0), + d_pdu(new uint8_t[max_len]) +{ + 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); + } + + /* Parameters checking */ + if (max_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 (var_len) { + d_length_field_len = 1; + } } ieee802_15_4_variant_decoder::~ieee802_15_4_variant_decoder() { + delete [] d_pdu; +} + +decoder_status_t +ieee802_15_4_variant_decoder::decode(const void *in, int len) +{ + if (d_var_len) { + return decode_var_len(in, len); + } + return decode_const_len(in, len); +} + +void +ieee802_15_4_variant_decoder::reset() +{ + if (d_descrambler) { + d_descrambler->reset(); + } + d_cnt = 0; + d_state = SEARCHING; + d_preamble_shift_reg.reset(); + d_sync_shift_reg.reset(); +} + +decoder_status_t +ieee802_15_4_variant_decoder::decode_var_len(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_GENERIC_FRAME_LEN: + status.consumed = decode_frame_len((const uint8_t *) in); + break; + case DECODING_PAYLOAD: + decode_payload(status, (const uint8_t *) in, len); + break; + default: + throw std::runtime_error("ieee802_15_4_variant_decoder: Invalid state"); + } + return status; +} + +decoder_status_t +ieee802_15_4_variant_decoder::decode_const_len(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_preamble((const uint8_t *) in, len); + break; + case DECODING_PAYLOAD: + decode_payload(status, (const uint8_t *) in, len); + break; + default: + throw std::runtime_error("ieee802_15_4_variant_decoder: Invalid state"); + } + return status; +} + +/** + * To greatly simplify the logic, the decoder requests that the number of + * input items should be a multiple of 8 + * @return 8 + */ +size_t +ieee802_15_4_variant_decoder::input_multiple() const +{ + return 8; +} + +int +ieee802_15_4_variant_decoder::search_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 +ieee802_15_4_variant_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) { + if (d_var_len) { + d_state = DECODING_GENERIC_FRAME_LEN; + } + else { + d_state = DECODING_PAYLOAD; + } + 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 +ieee802_15_4_variant_decoder::decode_frame_len(const uint8_t *in) +{ + uint8_t b = 0x0; + b |= in[0] << 7; + b |= in[1] << 6; + b |= in[2] << 5; + b |= in[3] << 4; + b |= in[4] << 3; + b |= in[5] << 2; + b |= in[6] << 1; + b |= in[7]; + + if (d_descrambler) { + uint8_t descrambled = 0x0; + d_descrambler->descramble((uint8_t *)&descrambled, + (const uint8_t *)&b, 1, false); + d_len = descrambled; + d_pdu[0] = descrambled; + } + else { + d_len = b; + d_pdu[0] = b; + } + d_len += crc::crc_size(d_crc); + /* Length field is needed for the CRC calculation */ + d_cnt = 1; + d_state = DECODING_PAYLOAD; + return 8; +} + +void +ieee802_15_4_variant_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 + d_length_field_len) { + if (d_descrambler) { + d_descrambler->descramble(d_pdu + d_length_field_len, + d_pdu + d_length_field_len, d_len, false); + } + + status.decode_success = true; + status.consumed = (i + 1) * 8; + if (check_crc()) { + metadata::add_time_iso8601(status.data); + metadata::add_pdu(status.data, d_pdu + d_length_field_len, + d_len - crc::crc_size(d_crc)); + metadata::add_crc_valid(status.data, true); + } + else { + metadata::add_pdu(status.data, d_pdu + d_length_field_len, d_len); + metadata::add_crc_valid(status.data, false); + } + reset(); + return; + } + } + status.consumed = s * 8; +} + +bool +ieee802_15_4_variant_decoder::check_crc() +{ + uint16_t crc16_c; + uint16_t crc16_received; + switch (d_crc) { + case crc::CRC_NONE: + return true; + case crc::CRC16_CCITT: + crc16_c = crc::crc16_ccitt(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_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); + if (crc16_c == crc16_received) { + return true; + } + return false; + case crc::CRC16_CCITT_REVERSED: + crc16_c = crc::crc16_ccitt_reversed(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_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); + if (crc16_c == crc16_received) { + return true; + } + return false; + case crc::CRC16_IBM: + 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); + if (crc16_c == crc16_received) { + return true; + } + return false; + default: + throw std::runtime_error("ieee802_15_4_variant_decoder: Invalid CRC"); + } } } /* namespace satnogs */ diff --git a/swig/satnogs_swig0.i b/swig/satnogs_swig0.i index 6709e0c..5e861ba 100644 --- a/swig/satnogs_swig0.i +++ b/swig/satnogs_swig0.i @@ -43,16 +43,18 @@ #include "satnogs/lrpt_sync.h" #include "satnogs/metadata.h" #include "satnogs/crc.h" +#include "satnogs/ieee802_15_4_variant_decoder.h" %} +%include "satnogs/whitening.h" %include "satnogs/morse_tree.h" %include "satnogs/decoder.h" %include "satnogs/amsat_duv_decoder.h" %include "satnogs/ax25_decoder.h" %include "satnogs/metadata.h" %include "satnogs/crc.h" - +%include "satnogs/ieee802_15_4_variant_decoder.h" %include "satnogs/morse_decoder.h" GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder); @@ -81,8 +83,6 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, doppler_correction_cc); %include "satnogs/upsat_fsk_frame_encoder.h" GR_SWIG_BLOCK_MAGIC2(satnogs, upsat_fsk_frame_encoder); -%include "satnogs/whitening.h" - %include "satnogs/udp_msg_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, udp_msg_sink);