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 @@
Decodersvariable_ax25_decodervariable_amsat_duv_decoder
+ variable_ieee802_15_4_variant_decoderSatellites
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);