Commit 2fb1bfad authored by Manolis Surligas's avatar Manolis Surligas

Fix AX.25 encoder/decoder

* Force the left over scrambled bits into the LFSR to be transmitted
* Refactor the decoding process
parent d7f8d7db
This diff is collapsed.
<?xml version="1.0"?>
<block>
<name>AX.25 Decoder</name>
<key>satnogs_ax25_decoder_bm</key>
<import>import satnogs</import>
<make>satnogs.ax25_decoder_bm($addr, $ssid, $promisc, $descrambling, $max_frame_len, $n_sync_flags)</make>
<name>AX.25 Decoder</name>
<key>satnogs_ax25_decoder_bm</key>
<import>import satnogs</import>
<make>satnogs.ax25_decoder_bm($addr, $ssid, $promisc, $descrambling, $max_frame_len)</make>
<param>
<name>Receiver Callsign</name>
<key>addr</key>
<value>'GND'</value>
<type>string</type>
</param>
<param>
<name>Receiver Callsign</name>
<key>addr</key>
<value>'GND'</value>
<type>string</type>
</param>
<param>
<name>Receiver SSID</name>
<key>ssid</key>
<value>0</value>
<type>int</type>
</param>
<param>
<name>Receiver SSID</name>
<key>ssid</key>
<value>0</value>
<type>int</type>
</param>
<param>
<name>Promiscuous mode</name>
<key>promisc</key>
<type>enum</type>
<option>
<name>No</name>
<key>False</key>
</option>
<option>
<name>Yes</name>
<key>True</key>
</option>
</param>
<param>
<name>Promiscuous mode</name>
<key>promisc</key>
<type>enum</type>
<option>
<name>No</name>
<key>False</key>
</option>
<option>
<name>Yes</name>
<key>True</key>
</option>
</param>
<param>
<name>G3RUH descrambling</name>
<key>descrambling</key>
<type>enum</type>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<param>
<name>G3RUH descrambling</name>
<key>descrambling</key>
<type>enum</type>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<param>
<name>Maximum frame length</name>
<key>max_frame_len</key>
<value>256</value>
<type>int</type>
</param>
<param>
<name>AX.25 Leading SYNC flags Threshold</name>
<key>n_sync_flags</key>
<value>2</value>
<type>int</type>
</param>
<param>
<name>Maximum frame length</name>
<key>max_frame_len</key>
<value>256</value>
<type>int</type>
</param>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>pdu</name>
<type>message</type>
</source>
<source>
<name>pdu</name>
<type>message</type>
</source>
<source>
<name>failed_pdu</name>
<type>message</type>
<optional>1</optional>
</source>
<source>
<name>failed_pdu</name>
<type>message</type>
<optional>1</optional>
</source>
</block>
......@@ -334,7 +334,7 @@ namespace gr
/* Check if bit stuffing should be applied */
if ((shift_reg & 0x1F) == 0x1F) {
out[out_idx++] = 0x0;
shift_reg = 0x0;
shift_reg <<= 1;
}
}
......
......@@ -2,7 +2,7 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, 2017
* Copyright (C) 2016, 2017, 2018
* Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
......@@ -75,17 +75,11 @@ namespace gr
* @param descramble if set to yes, the data will be descrambled prior
* decoding using the G3RUH self-synchronizing descrambler.
* @param max_frame_len the maximum allowed frame length
* @param n_sync_flags the number of the leading AX.25 SYNC flag
* repetitions. Normally the SYNC flag is repeated multiple times
* prior the payload transmission. Increasing this parameter
* reduces significantly the false alarms
* @return
*/
static sptr
make (const std::string& addr, uint8_t ssid, bool promisc = false,
bool descramble = true,
size_t max_frame_len = 512,
size_t n_sync_flags = 2);
bool descramble = true, size_t max_frame_len = 512);
};
} // namespace satnogs
......
This diff is collapsed.
......@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
* Copyright (C) 2016,2018
* Libre Space Foundation <http://librespacefoundation.org/>
*
* 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
......@@ -34,7 +35,7 @@ namespace gr
private:
typedef enum
{
NO_SYNC, IN_SYNC, DECODING, FRAME_END
NO_SYNC, IN_SYNC, DECODING, FRAME_END
} decoding_state_t;
/**
......@@ -44,13 +45,11 @@ namespace gr
const bool d_promisc;
const bool d_descramble;
const size_t d_max_frame_len;
const size_t d_sync_flags_thr;
decoding_state_t d_state;
uint8_t d_shift_reg;
uint8_t d_dec_b;
uint8_t d_prev_bit_nrzi;
size_t d_received_bytes;
size_t d_sync_received;
size_t d_decoded_bits;
digital::lfsr d_lfsr;
uint8_t *d_frame_buffer;
......@@ -64,21 +63,26 @@ namespace gr
void
enter_frame_end ();
void
size_t
descramble_and_decode (const uint8_t *in, size_t nitems);
void
size_t
decode (const uint8_t *in, size_t nitems);
inline void
descramble_and_decode_1b (uint8_t in);
inline void
decode_1b (uint8_t in);
public:
ax25_decoder_bm_impl (const std::string& addr, uint8_t ssid, bool promisc,
bool descramble, size_t max_frame_len,
size_t n_sync_flags);
bool descramble, size_t max_frame_len);
~ax25_decoder_bm_impl ();
// Where all the action really happens
int
work (int noutput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
gr_vector_void_star &output_items);
};
} // namespace satnogs
......
......@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
* Copyright (C) 2016,2018
* Libre Space Foundation <http://librespacefoundation.org/>
*
* 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
......@@ -34,46 +35,46 @@ namespace gr
ax25_encoder_mb::sptr
ax25_encoder_mb::make (const std::string& dest_addr, uint8_t dest_ssid,
const std::string& src_addr, uint8_t src_ssid,
size_t preamble_len, size_t postamble_len,
bool scramble)
const std::string& src_addr, uint8_t src_ssid,
size_t preamble_len, size_t postamble_len,
bool scramble)
{
return gnuradio::get_initial_sptr (
new ax25_encoder_mb_impl (dest_addr, dest_ssid, src_addr, src_ssid,
preamble_len, postamble_len, scramble));
new ax25_encoder_mb_impl (dest_addr, dest_ssid, src_addr, src_ssid,
preamble_len, postamble_len, scramble));
}
/*
* The private constructor
*/
ax25_encoder_mb_impl::ax25_encoder_mb_impl (const std::string& dest_addr,
uint8_t dest_ssid,
const std::string& src_addr,
uint8_t src_ssid,
size_t preamble_len,
size_t postabmle_len,
bool scramble) :
gr::sync_block ("ax25_encoder_mb", gr::io_signature::make (0, 0, 0),
gr::io_signature::make (1, 1, sizeof(uint8_t))),
d_preamble_len (preamble_len),
d_postamble_len (postabmle_len),
d_scramble(scramble),
d_remaining (0),
d_produced (0),
d_prev_bit(0x0),
d_encoded_frame (
new uint8_t[preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)]),
d_tmp_buf (
new uint8_t[preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)]),
d_addr_field (new uint8_t[AX25_MAX_ADDR_LEN]),
d_lfsr(0x21, 0x0, 16)
uint8_t dest_ssid,
const std::string& src_addr,
uint8_t src_ssid,
size_t preamble_len,
size_t postabmle_len,
bool scramble) :
gr::sync_block ("ax25_encoder_mb", gr::io_signature::make (0, 0, 0),
gr::io_signature::make (1, 1, sizeof(uint8_t))),
d_preamble_len (preamble_len),
d_postamble_len (postabmle_len),
d_scramble (scramble),
d_remaining (0),
d_produced (0),
d_prev_bit (0x0),
d_encoded_frame (
new uint8_t[(preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)) * 8]),
d_tmp_buf (
new uint8_t[preamble_len + postabmle_len
+ (AX25_MAX_FRAME_LEN * 2)]),
d_addr_field (new uint8_t[AX25_MAX_ADDR_LEN]),
d_lfsr (0x21, 0x0, 16)
{
/* Input is a blob message containing the info field data */
message_port_register_in (pmt::mp ("info"));
d_addr_len = ax25_create_addr_field(d_addr_field, dest_addr, dest_ssid,
src_addr, src_ssid);
d_addr_len = ax25_create_addr_field (d_addr_field, dest_addr, dest_ssid,
src_addr, src_ssid);
}
/*
......@@ -88,8 +89,8 @@ namespace gr
int
ax25_encoder_mb_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const uint8_t *info;
size_t info_len;
......@@ -103,59 +104,63 @@ namespace gr
/* If all the frame samples have already be sent, wait for a new frame */
if (d_remaining == 0) {
boost::mutex::scoped_lock lock (d_mutex);
d_produced = 0;
d_prev_bit = 0x0;
d_lfsr.reset();
/* Block waiting from a new message from users */
msg = delete_head_blocking (pmt::mp ("info"));
info = (const uint8_t *)pmt::blob_data(msg);
info_len = pmt::blob_length(msg);
/* Prepare and encode the AX.25 frame */
len = ax25_prepare_frame (d_tmp_buf, info, info_len, AX25_I_FRAME,
d_addr_field, d_addr_len, 0, 1,
d_preamble_len, d_postamble_len);
/* Perform bit stuffing */
status = ax25_bit_stuffing (d_encoded_frame, &d_remaining, d_tmp_buf,
len, d_preamble_len, d_postamble_len);
if (status != AX25_ENC_OK) {
LOG_ERROR ("AX.25 encoding failed");
d_remaining = 0;
return 0;
}
/*Perform scrambling if the user asked for it */
if(d_scramble){
for(i = 0; i < d_remaining; i++){
d_encoded_frame[i] = d_lfsr.next_bit_scramble(d_encoded_frame[i]);
}
}
/* If this is the first part of the frame add the start of burst tag*/
if (d_produced == 0) {
add_sob (nitems_written (0));
}
max_avail = std::min (d_remaining, (size_t) noutput_items);
/* Perform NRZI encoding */
for(i = 0; i < max_avail; i++) {
out[i] = ( (0x1 & ~d_encoded_frame[i + d_produced]) + d_prev_bit) % 2;
d_prev_bit = out[i];
}
d_remaining -= max_avail;
d_produced += max_avail;
if (d_remaining == 0) {
add_eob (nitems_written (0) + max_avail);
}
return (int) max_avail;
d_produced = 0;
d_prev_bit = 0x0;
d_lfsr.reset ();
/* Block waiting from a new message from users */
msg = delete_head_blocking (pmt::mp ("info"));
info = (const uint8_t *) pmt::blob_data (msg);
info_len = pmt::blob_length (msg);
/* Prepare and encode the AX.25 frame */
len = ax25_prepare_frame (d_tmp_buf, info, info_len, AX25_I_FRAME,
d_addr_field, d_addr_len, 0, 1,
d_preamble_len, d_postamble_len);
/* Perform bit stuffing */
status = ax25_bit_stuffing (d_encoded_frame, &d_remaining, d_tmp_buf,
len, d_preamble_len, d_postamble_len);
if (status != AX25_ENC_OK) {
LOG_ERROR("AX.25 encoding failed");
d_remaining = 0;
return 0;
}
/*Perform scrambling if the user asked for it */
if (d_scramble) {
for (i = 0; i < d_remaining; i++) {
d_encoded_frame[i] = d_lfsr.next_bit_scramble (d_encoded_frame[i]);
}
/* Allow the LFSR to pop all its bits */
d_remaining += 16;
for (; i < d_remaining; i++) {
d_encoded_frame[i] = d_lfsr.next_bit_scramble (0x0);
}
}
/* Append a zero byte at the end */
memset(&d_encoded_frame[d_remaining], 0, 8);
d_remaining += 8;
}
// Tell runtime system how many output items we produced.
return noutput_items;
/* If this is the first part of the frame add the start of burst tag*/
if (d_produced == 0) {
add_sob (nitems_written (0));
}
max_avail = std::min (d_remaining, (size_t) noutput_items);
/* Perform NRZI encoding */
for (i = 0; i < max_avail; i++) {
out[i] = ((0x1 & ~d_encoded_frame[i + d_produced]) + d_prev_bit) % 2;
d_prev_bit = out[i];
}
d_remaining -= max_avail;
d_produced += max_avail;
if (d_remaining == 0) {
add_eob (nitems_written (0) + max_avail);
}
return (int) max_avail;
}
......
......@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
* Copyright (C) 2016,2018
* Libre Space Foundation <http://librespacefoundation.org/>
*
* 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
......@@ -43,7 +44,6 @@ namespace gr
uint8_t *d_addr_field;
size_t d_addr_len;
digital::lfsr d_lfsr;
boost::mutex d_mutex;
void
add_sob (uint64_t item);
......@@ -52,15 +52,15 @@ namespace gr
public:
ax25_encoder_mb_impl (const std::string& dest_addr, uint8_t dest_ssid,
const std::string& src_addr, uint8_t src_ssid,
size_t preamble_len, size_t postamble_len,
bool scramble);
const std::string& src_addr, uint8_t src_ssid,
size_t preamble_len, size_t postamble_len,
bool scramble);
~ax25_encoder_mb_impl ();
// Where all the action really happens
int
work (int noutput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
gr_vector_void_star &output_items);
};
} // namespace satnogs
......
......@@ -55,7 +55,8 @@ namespace gr
if(d_timestamp) {
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
d_fos << "[" << strftime(buf, sizeof(buf), "%F %T %z", &tm) << "]";
strftime(buf, sizeof(buf), "%F %T %z", &tm);
d_fos << "[" << buf << "]";
}
switch (d_format)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment