From c40b83211f00ccde70be7f7940897ad8743d45cc Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Thu, 12 Sep 2019 19:45:45 +0300 Subject: [PATCH] Add a IEEE 802.15.4 compatible decoder Add a IEEE 802.15.4 like decoder, which supports the IEEE 802.15.4 standard but also a large variety of ICs based on this framing scheme. Such framings are quite common in many Cubesat missions. The decoder has been tested an works well with at least the Reaktor Hello World satellite --- README.md | 83 +++-- grc/CMakeLists.txt | 1 + grc/satnogs_block_tree.xml | 1 + grc/satnogs_ieee802_15_4_variant_decoder.xml | 80 +++++ include/satnogs/crc.h | 18 +- include/satnogs/decoder.h | 3 + .../satnogs/ieee802_15_4_variant_decoder.h | 106 +++++- lib/crc.cc | 21 ++ lib/decoder.cc | 16 + lib/frame_decoder_impl.cc | 8 + lib/ieee802_15_4_variant_decoder.cc | 329 +++++++++++++++++- swig/satnogs_swig0.i | 6 +- 12 files changed, 623 insertions(+), 49 deletions(-) create mode 100644 grc/satnogs_ieee802_15_4_variant_decoder.xml 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);