AX.25 support at the UPSAT FSK encoder/decoder
This commit is contained in:
parent
652c257b01
commit
e79e98fbd8
|
@ -4,7 +4,7 @@
|
||||||
<key>satnogs_upsat_fsk_frame_encoder</key>
|
<key>satnogs_upsat_fsk_frame_encoder</key>
|
||||||
<category>satnogs</category>
|
<category>satnogs</category>
|
||||||
<import>import satnogs</import>
|
<import>import satnogs</import>
|
||||||
<make>satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester, $msb_first, $ax_25, $settling_samples)</make>
|
<make>satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester, $msb_first, $ax_25, $src_addr, $src_ssid, $dest_addr, $dest_ssid, $settling_samples)</make>
|
||||||
|
|
||||||
<param>
|
<param>
|
||||||
<name>Frame Preamble</name>
|
<name>Frame Preamble</name>
|
||||||
|
@ -88,6 +88,30 @@
|
||||||
</option>
|
</option>
|
||||||
</param>
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Destination Callsign</name>
|
||||||
|
<key>dest_addr</key>
|
||||||
|
<type>string</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Destination SSID</name>
|
||||||
|
<key>dest_ssid</key>
|
||||||
|
<type>int</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Source Callsign</name>
|
||||||
|
<key>src_addr</key>
|
||||||
|
<type>string</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
|
<param>
|
||||||
|
<name>Source SSID</name>
|
||||||
|
<key>src_ssid</key>
|
||||||
|
<type>int</type>
|
||||||
|
</param>
|
||||||
|
|
||||||
<param>
|
<param>
|
||||||
<name>Number of zero settling samples</name>
|
<name>Number of zero settling samples</name>
|
||||||
<key>settling_samples</key>
|
<key>settling_samples</key>
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#define INCLUDE_SATNOGS_AX25_H_
|
#define INCLUDE_SATNOGS_AX25_H_
|
||||||
|
|
||||||
#include <satnogs/utils.h>
|
#include <satnogs/utils.h>
|
||||||
|
#include <satnogs/log.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
{
|
{
|
||||||
|
@ -44,7 +46,8 @@ namespace gr
|
||||||
{
|
{
|
||||||
AX25_I_FRAME, //!< AX25_I_FRAME Information frame
|
AX25_I_FRAME, //!< AX25_I_FRAME Information frame
|
||||||
AX25_S_FRAME, //!< AX25_S_FRAME Supervisory frame
|
AX25_S_FRAME, //!< AX25_S_FRAME Supervisory frame
|
||||||
AX25_U_FRAME //!< AX25_U_FRAME Unnumbered frame
|
AX25_U_FRAME, //!< AX25_U_FRAME Unnumbered frame
|
||||||
|
AX25_UI_FRAME /**!< AX25_UI_FRAME Unnumbered information frame */
|
||||||
} ax25_frame_type_t;
|
} ax25_frame_type_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -53,6 +56,12 @@ namespace gr
|
||||||
AX25_ENC_OK
|
AX25_ENC_OK
|
||||||
} ax25_encode_status_t;
|
} ax25_encode_status_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
AX25_DEC_FAIL,
|
||||||
|
AX25_DEC_OK
|
||||||
|
} ax25_decode_status_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t address[AX25_MAX_ADDR_LEN];
|
uint8_t address[AX25_MAX_ADDR_LEN];
|
||||||
|
@ -60,7 +69,8 @@ namespace gr
|
||||||
uint16_t ctrl;
|
uint16_t ctrl;
|
||||||
size_t ctrl_len;
|
size_t ctrl_len;
|
||||||
uint8_t pid;
|
uint8_t pid;
|
||||||
uint8_t info[AX25_MAX_FRAME_LEN];
|
uint8_t *info;
|
||||||
|
size_t info_len;
|
||||||
ax25_frame_type_t type;
|
ax25_frame_type_t type;
|
||||||
} ax25_frame_t;
|
} ax25_frame_t;
|
||||||
|
|
||||||
|
@ -75,7 +85,7 @@ namespace gr
|
||||||
{
|
{
|
||||||
uint16_t fcs = 0xFFFF;
|
uint16_t fcs = 0xFFFF;
|
||||||
while (len--) {
|
while (len--) {
|
||||||
fcs = (fcs >> 8) ^ crc16_ccitt_table_reverse[(fcs ^ *buffer++) & 0XFF];
|
fcs = (fcs >> 8) ^ crc16_ccitt_table_reverse[(fcs ^ *buffer++) & 0xFF];
|
||||||
}
|
}
|
||||||
return fcs ^ 0xFFFF;
|
return fcs ^ 0xFFFF;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +156,7 @@ namespace gr
|
||||||
|
|
||||||
if( ctrl_len == AX25_MIN_CTRL_LEN || ctrl_len == AX25_MAX_CTRL_LEN){
|
if( ctrl_len == AX25_MIN_CTRL_LEN || ctrl_len == AX25_MAX_CTRL_LEN){
|
||||||
memcpy(out + i, &ctrl, ctrl_len);
|
memcpy(out + i, &ctrl, ctrl_len);
|
||||||
i += addr_len;
|
i += ctrl_len;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -157,7 +167,7 @@ namespace gr
|
||||||
* FIXME: For now, only the "No layer 3 is implemented" information is
|
* FIXME: For now, only the "No layer 3 is implemented" information is
|
||||||
* inserted
|
* inserted
|
||||||
*/
|
*/
|
||||||
if(type == AX25_I_FRAME){
|
if (type == AX25_I_FRAME || type == AX25_UI_FRAME) {
|
||||||
out[i++] = 0xF0;
|
out[i++] = 0xF0;
|
||||||
}
|
}
|
||||||
memcpy(out + i, info, info_len);
|
memcpy(out + i, info, info_len);
|
||||||
|
@ -315,6 +325,104 @@ namespace gr
|
||||||
return AX25_ENC_OK;
|
return AX25_ENC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ax25_decode_status_t
|
||||||
|
ax25_decode (uint8_t *out, size_t *out_len,
|
||||||
|
const uint8_t *ax25_frame, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t frame_start = UINT_MAX;
|
||||||
|
size_t frame_stop = UINT_MAX;
|
||||||
|
uint8_t res;
|
||||||
|
size_t cont_1 = 0;
|
||||||
|
size_t received_bytes = 0;
|
||||||
|
size_t bit_cnt = 0;
|
||||||
|
uint8_t decoded_byte = 0x0;
|
||||||
|
uint16_t fcs;
|
||||||
|
uint16_t recv_fcs;
|
||||||
|
|
||||||
|
|
||||||
|
/* Start searching for the SYNC flag */
|
||||||
|
for(i = 0; i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN); i++) {
|
||||||
|
res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]);
|
||||||
|
/* Found it! */
|
||||||
|
if(res == 0){
|
||||||
|
frame_start = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We failed to find the SYNC flag */
|
||||||
|
if(frame_start == UINT_MAX){
|
||||||
|
return AX25_DEC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = frame_start + sizeof(AX25_SYNC_FLAG_MAP_BIN);
|
||||||
|
i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN); i++) {
|
||||||
|
/* Check if we reached the frame end */
|
||||||
|
res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) |
|
||||||
|
(AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]);
|
||||||
|
/* Found it! */
|
||||||
|
if(res == 0){
|
||||||
|
frame_stop = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ax25_frame[i]) {
|
||||||
|
cont_1++;
|
||||||
|
decoded_byte |= 1 << bit_cnt;
|
||||||
|
bit_cnt++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* If 5 consecutive 1's drop the extra zero*/
|
||||||
|
if (cont_1 >= 5) {
|
||||||
|
cont_1 = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
bit_cnt++;
|
||||||
|
cont_1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill the fully constructed byte */
|
||||||
|
if(bit_cnt == 8){
|
||||||
|
out[received_bytes++] = decoded_byte;
|
||||||
|
bit_cnt = 0;
|
||||||
|
decoded_byte = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(frame_stop == UINT_MAX || received_bytes < AX25_MIN_ADDR_LEN){
|
||||||
|
return AX25_DEC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check the CRC */
|
||||||
|
fcs = ax25_fcs (out, received_bytes - sizeof(uint16_t));
|
||||||
|
recv_fcs = (((uint16_t) out[received_bytes - 2]) << 8)
|
||||||
|
| out[received_bytes - 1];
|
||||||
|
|
||||||
|
if(fcs != recv_fcs) {
|
||||||
|
LOG_WARN("AX.25 CRC-16 failed");
|
||||||
|
return AX25_DEC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = received_bytes - sizeof(uint16_t);
|
||||||
|
return AX25_DEC_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace satnogs
|
} // namespace satnogs
|
||||||
|
|
||||||
} // namespace gr
|
} // namespace gr
|
||||||
|
|
|
@ -63,7 +63,10 @@ namespace gr
|
||||||
* the Manchester algorithm of the CC1120 chip. False otherwise.
|
* the Manchester algorithm of the CC1120 chip. False otherwise.
|
||||||
*
|
*
|
||||||
* @param msb_first if set to true, the the treansmission starts from the
|
* @param msb_first if set to true, the the treansmission starts from the
|
||||||
* MSB of each byte.
|
* MSB of each byte. In case the AX.25 encapuslation is selected, this
|
||||||
|
* parameter is NOT taken into consideration for the AX.25 part,
|
||||||
|
* as the AX.25 dictates that the LS bit should be sent first.
|
||||||
|
*
|
||||||
* @param ax25_format if set to true the frame payload will be encoded
|
* @param ax25_format if set to true the frame payload will be encoded
|
||||||
* using AX.25 encapsulation.
|
* using AX.25 encapsulation.
|
||||||
*
|
*
|
||||||
|
@ -78,11 +81,16 @@ namespace gr
|
||||||
static sptr
|
static sptr
|
||||||
make (const std::vector<uint8_t>& preamble,
|
make (const std::vector<uint8_t>& preamble,
|
||||||
const std::vector<uint8_t>& sync_word,
|
const std::vector<uint8_t>& sync_word,
|
||||||
bool append_crc = true,
|
bool append_crc,
|
||||||
bool whitening = false, bool manchester = false,
|
bool whitening,
|
||||||
bool msb_first = true,
|
bool manchester,
|
||||||
bool ax25_format = false,
|
bool msb_first,
|
||||||
size_t settling_samples = 64);
|
bool ax25_format,
|
||||||
|
const std::string& ax25_dest_addr,
|
||||||
|
uint8_t ax25_dest_ssid,
|
||||||
|
const std::string& ax25_src_addr,
|
||||||
|
uint8_t ax25_src_ssid,
|
||||||
|
size_t settling_samples);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace satnogs
|
} // namespace satnogs
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <gnuradio/io_signature.h>
|
#include <gnuradio/io_signature.h>
|
||||||
#include "upsat_fsk_frame_acquisition_impl.h"
|
#include "upsat_fsk_frame_acquisition_impl.h"
|
||||||
#include <satnogs/log.h>
|
#include <satnogs/log.h>
|
||||||
|
#include <satnogs/ax25.h>
|
||||||
#include <satnogs/utils.h>
|
#include <satnogs/utils.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
@ -97,6 +98,8 @@ namespace gr
|
||||||
}
|
}
|
||||||
|
|
||||||
d_pdu = new uint8_t[UPSAT_MAX_FRAME_LEN];
|
d_pdu = new uint8_t[UPSAT_MAX_FRAME_LEN];
|
||||||
|
d_ax25_tmp_buf = new uint8_t[2 * UPSAT_MAX_FRAME_LEN * 8];
|
||||||
|
d_ax25_buf = new uint8_t[2 * UPSAT_MAX_FRAME_LEN];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -105,6 +108,8 @@ namespace gr
|
||||||
upsat_fsk_frame_acquisition_impl::~upsat_fsk_frame_acquisition_impl ()
|
upsat_fsk_frame_acquisition_impl::~upsat_fsk_frame_acquisition_impl ()
|
||||||
{
|
{
|
||||||
delete[] d_pdu;
|
delete[] d_pdu;
|
||||||
|
delete[] d_ax25_tmp_buf;
|
||||||
|
delete[] d_ax25_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -173,6 +178,23 @@ namespace gr
|
||||||
d_decoded_bits = 0;
|
d_decoded_bits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
upsat_fsk_frame_acquisition_impl::unpack_ax25_bytes (size_t len_bytes)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
uint8_t *in = d_pdu + 1;
|
||||||
|
for(i = 0; i < len_bytes; i++){
|
||||||
|
d_ax25_tmp_buf[8*i] = (in[i] >> 7) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 1] = (in[i] >> 6) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 2] = (in[i] >> 5) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 3] = (in[i] >> 4) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 4] = (in[i] >> 3) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 5] = (in[i] >> 2) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 6] = (in[i] >> 1) & 0x1;
|
||||||
|
d_ax25_tmp_buf[8*i + 7] = in[i] & 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
upsat_fsk_frame_acquisition_impl::work (
|
upsat_fsk_frame_acquisition_impl::work (
|
||||||
int noutput_items, gr_vector_const_void_star &input_items,
|
int noutput_items, gr_vector_const_void_star &input_items,
|
||||||
|
@ -181,6 +203,8 @@ namespace gr
|
||||||
int i;
|
int i;
|
||||||
uint16_t crc_received;
|
uint16_t crc_received;
|
||||||
uint16_t crc_calc;
|
uint16_t crc_calc;
|
||||||
|
size_t ax25_frame_len = 0;
|
||||||
|
ax25_decode_status_t status;
|
||||||
const float *in = (const float *) input_items[0];
|
const float *in = (const float *) input_items[0];
|
||||||
for (i = 0; i < noutput_items; i++) {
|
for (i = 0; i < noutput_items; i++) {
|
||||||
slice_and_shift (in[i]);
|
slice_and_shift (in[i]);
|
||||||
|
@ -273,9 +297,30 @@ namespace gr
|
||||||
d_decoded_bytes++;
|
d_decoded_bytes++;
|
||||||
|
|
||||||
if (d_decoded_bytes == d_frame_len) {
|
if (d_decoded_bytes == d_frame_len) {
|
||||||
|
if(d_is_ax25) {
|
||||||
|
unpack_ax25_bytes(d_frame_len - 1);
|
||||||
|
status = ax25_decode(d_ax25_buf, &ax25_frame_len,
|
||||||
|
d_ax25_tmp_buf, (d_frame_len - 1)*8);
|
||||||
|
if(status == AX25_DEC_OK){
|
||||||
|
message_port_pub (pmt::mp ("pdu"),
|
||||||
|
pmt::make_blob(d_ax25_buf, ax25_frame_len));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
LOG_WARN("AX.25 decoding failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are done here. Whitening and FSK CRC is not supported
|
||||||
|
* when transmitting/receiving AX.25 frames
|
||||||
|
*/
|
||||||
|
reset_state ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(d_whitening){
|
if(d_whitening){
|
||||||
d_descrambler.descramble(d_pdu+1, d_pdu+1, d_frame_len - 1);
|
d_descrambler.descramble(d_pdu+1, d_pdu+1, d_frame_len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!d_check_crc){
|
if(!d_check_crc){
|
||||||
message_port_pub (
|
message_port_pub (
|
||||||
pmt::mp ("pdu"),
|
pmt::mp ("pdu"),
|
||||||
|
|
|
@ -63,6 +63,8 @@ namespace gr
|
||||||
size_t d_frame_len;
|
size_t d_frame_len;
|
||||||
whitening d_descrambler;
|
whitening d_descrambler;
|
||||||
uint8_t *d_pdu;
|
uint8_t *d_pdu;
|
||||||
|
uint8_t *d_ax25_tmp_buf;
|
||||||
|
uint8_t *d_ax25_buf;
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
slice_and_shift (float in);
|
slice_and_shift (float in);
|
||||||
|
@ -79,6 +81,8 @@ namespace gr
|
||||||
have_frame_len ();
|
have_frame_len ();
|
||||||
inline void
|
inline void
|
||||||
have_payload ();
|
have_payload ();
|
||||||
|
inline void
|
||||||
|
unpack_ax25_bytes(size_t len_bytes);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
upsat_fsk_frame_acquisition_impl (const std::vector<uint8_t> &preamble,
|
upsat_fsk_frame_acquisition_impl (const std::vector<uint8_t> &preamble,
|
||||||
|
|
|
@ -37,9 +37,12 @@ namespace gr
|
||||||
upsat_fsk_frame_encoder::make (const std::vector<uint8_t>& preamble,
|
upsat_fsk_frame_encoder::make (const std::vector<uint8_t>& preamble,
|
||||||
const std::vector<uint8_t>& sync_word,
|
const std::vector<uint8_t>& sync_word,
|
||||||
bool append_crc, bool whitening,
|
bool append_crc, bool whitening,
|
||||||
bool manchester,
|
bool manchester, bool msb_first,
|
||||||
bool msb_first,
|
|
||||||
bool ax25_format,
|
bool ax25_format,
|
||||||
|
const std::string& ax25_dest_addr,
|
||||||
|
uint8_t ax25_dest_ssid,
|
||||||
|
const std::string& ax25_src_addr,
|
||||||
|
uint8_t ax25_src_ssid,
|
||||||
size_t settling_samples)
|
size_t settling_samples)
|
||||||
{
|
{
|
||||||
return gnuradio::get_initial_sptr (
|
return gnuradio::get_initial_sptr (
|
||||||
|
@ -47,6 +50,8 @@ namespace gr
|
||||||
append_crc,
|
append_crc,
|
||||||
whitening, manchester,
|
whitening, manchester,
|
||||||
msb_first, ax25_format,
|
msb_first, ax25_format,
|
||||||
|
ax25_src_addr, ax25_src_ssid,
|
||||||
|
ax25_dest_addr, ax25_dest_ssid,
|
||||||
settling_samples));
|
settling_samples));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +64,10 @@ namespace gr
|
||||||
bool append_crc, bool whitening,
|
bool append_crc, bool whitening,
|
||||||
bool manchester, bool msb_first,
|
bool manchester, bool msb_first,
|
||||||
bool ax25_format,
|
bool ax25_format,
|
||||||
|
const std::string& ax25_dest_addr,
|
||||||
|
uint8_t ax25_dest_ssid,
|
||||||
|
const std::string& ax25_src_addr,
|
||||||
|
uint8_t ax25_src_ssid,
|
||||||
size_t settling_samples) :
|
size_t settling_samples) :
|
||||||
gr::sync_block ("upsat_fsk_frame_encoder",
|
gr::sync_block ("upsat_fsk_frame_encoder",
|
||||||
gr::io_signature::make (0, 0, 0),
|
gr::io_signature::make (0, 0, 0),
|
||||||
|
@ -91,6 +100,18 @@ namespace gr
|
||||||
* User def. User def. 1B 1-255 B 2 B
|
* User def. User def. 1B 1-255 B 2 B
|
||||||
*/
|
*/
|
||||||
d_pdu = new uint8_t[d_max_pdu_len];
|
d_pdu = new uint8_t[d_max_pdu_len];
|
||||||
|
|
||||||
|
|
||||||
|
if(d_is_ax25){
|
||||||
|
d_ax25_addr = new uint8_t[AX25_MAX_ADDR_LEN];
|
||||||
|
/* One useful bit per byte for the AX.25 buffer */
|
||||||
|
d_ax25_pdu = new uint8_t[2 * d_max_pdu_len * 8];
|
||||||
|
d_ax25_tmp_buf = new uint8_t[d_max_pdu_len * 2];
|
||||||
|
d_ax25_addr_len = ax25_create_addr_field (d_ax25_addr, ax25_dest_addr,
|
||||||
|
ax25_dest_ssid, ax25_src_addr,
|
||||||
|
ax25_src_ssid);
|
||||||
|
}
|
||||||
|
|
||||||
d_pdu_encoded = new float[d_max_pdu_len*8 + d_settling_samples];
|
d_pdu_encoded = new float[d_max_pdu_len*8 + d_settling_samples];
|
||||||
|
|
||||||
/* Copy the preamble at the start of the pdu */
|
/* Copy the preamble at the start of the pdu */
|
||||||
|
@ -105,6 +126,11 @@ namespace gr
|
||||||
{
|
{
|
||||||
delete [] d_pdu;
|
delete [] d_pdu;
|
||||||
delete [] d_pdu_encoded;
|
delete [] d_pdu_encoded;
|
||||||
|
if(d_is_ax25) {
|
||||||
|
delete [] d_ax25_addr;
|
||||||
|
delete [] d_ax25_pdu;
|
||||||
|
delete [] d_ax25_tmp_buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -163,15 +189,13 @@ namespace gr
|
||||||
add_item_tag (0, item, eob_key, value, srcid);
|
add_item_tag (0, item, eob_key, value, srcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
inline int
|
||||||
upsat_fsk_frame_encoder_impl::work (int noutput_items,
|
upsat_fsk_frame_encoder_impl::raw_frame_handling (float* out,
|
||||||
gr_vector_const_void_star &input_items,
|
int noutput_items)
|
||||||
gr_vector_void_star &output_items)
|
|
||||||
{
|
{
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
size_t min_available;
|
size_t min_available;
|
||||||
pmt::pmt_t pdu;
|
pmt::pmt_t pdu;
|
||||||
float *out = (float *) output_items[0];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the whole previous frame has been successfully sent, block waiting
|
* If the whole previous frame has been successfully sent, block waiting
|
||||||
|
@ -245,7 +269,8 @@ namespace gr
|
||||||
min_available = std::min ((size_t) noutput_items,
|
min_available = std::min ((size_t) noutput_items,
|
||||||
(d_pdu_len - d_encoded) * 8);
|
(d_pdu_len - d_encoded) * 8);
|
||||||
|
|
||||||
memcpy(out, d_pdu_encoded + d_encoded*8, min_available * sizeof(float));
|
memcpy (out, d_pdu_encoded + d_encoded * 8,
|
||||||
|
min_available * sizeof(float));
|
||||||
d_encoded += min_available / 8;
|
d_encoded += min_available / 8;
|
||||||
|
|
||||||
/* End of the frame reached */
|
/* End of the frame reached */
|
||||||
|
@ -257,6 +282,128 @@ namespace gr
|
||||||
return min_available;
|
return min_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
upsat_fsk_frame_encoder_impl::ax25_frame_handling (float* out,
|
||||||
|
int noutput_items)
|
||||||
|
{
|
||||||
|
uint16_t crc;
|
||||||
|
size_t min_available;
|
||||||
|
pmt::pmt_t pdu;
|
||||||
|
size_t len;
|
||||||
|
size_t encoded_len;
|
||||||
|
ax25_encode_status_t status;
|
||||||
|
size_t extra_bits;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the whole previous frame has been successfully sent, block waiting
|
||||||
|
* for a new one
|
||||||
|
*/
|
||||||
|
if (d_encoded == 0) {
|
||||||
|
/* Reset the buffer */
|
||||||
|
memset(d_ax25_pdu, 0, 2 * d_max_pdu_len * 8);
|
||||||
|
pdu = delete_head_blocking (pmt::mp ("pdu"));
|
||||||
|
d_pdu_len = pmt::blob_length (pdu);
|
||||||
|
|
||||||
|
if (d_pdu_len > UPSAT_MAX_FRAME_LEN) {
|
||||||
|
LOG_ERROR("PDU is greater than the supported. Dropping the PDU");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ax25_prepare_frame(d_ax25_tmp_buf, (uint8_t *) pmt::blob_data (pdu),
|
||||||
|
d_pdu_len, AX25_UI_FRAME, d_ax25_addr,
|
||||||
|
d_ax25_addr_len, 0x03, 1);
|
||||||
|
status = ax25_bit_stuffing(d_ax25_pdu, &encoded_len,
|
||||||
|
d_ax25_tmp_buf, len);
|
||||||
|
if(status != AX25_ENC_OK) {
|
||||||
|
LOG_WARN("Failed to properly encode into AX.25 frame");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Due to bit stuffing the resulting bit number may not be
|
||||||
|
* a multiple of 8. Thus we append proper number of zeros
|
||||||
|
* after the SYNC flag. So neither the AX.25 or the FSK
|
||||||
|
* framing are affected
|
||||||
|
*/
|
||||||
|
extra_bits = 8 - (encoded_len % 8);
|
||||||
|
encoded_len += extra_bits;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the frame length at the corresponding field.
|
||||||
|
* NOTE: The frame length is calculated taking consideration only
|
||||||
|
* the address field (if exists) and the payload. Length and CRC fields
|
||||||
|
* are NOT included.
|
||||||
|
*/
|
||||||
|
d_pdu[d_preamble_len + d_sync_word_len] = (uint8_t) encoded_len;
|
||||||
|
|
||||||
|
/* If it is necessary calculate and append the CRC */
|
||||||
|
if (d_append_crc) {
|
||||||
|
LOG_WARN("AX.25 has its own CRC-16 field. Skipping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whitening can not be applied in the AX.25 because it will alter
|
||||||
|
* the SYNC flag of the stack
|
||||||
|
*/
|
||||||
|
if (d_whitening) {
|
||||||
|
LOG_WARN("AX.25 and whitening are not compatible."
|
||||||
|
" No whitening will be performed");
|
||||||
|
}
|
||||||
|
|
||||||
|
d_pdu_len = d_preamble_len + d_sync_word_len + 1 + encoded_len/8;
|
||||||
|
|
||||||
|
/* NRZ encoding the FSK preamble with the standard method */
|
||||||
|
map_msb_first (d_pdu_encoded, (d_preamble_len + d_sync_word_len + 1) * 8);
|
||||||
|
|
||||||
|
/* NRZ encode the AX.25 part of the FSK frame */
|
||||||
|
for(i = 0; i < encoded_len; i++){
|
||||||
|
d_pdu_encoded[i + (d_preamble_len + d_sync_word_len + 1)*8]
|
||||||
|
= (d_ax25_pdu[i] * 2.0f) - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the settling trailing samples */
|
||||||
|
memset (d_pdu_encoded + d_pdu_len * 8, 0,
|
||||||
|
d_settling_samples * sizeof(float));
|
||||||
|
|
||||||
|
/* The new frame now has a bigger size of course*/
|
||||||
|
d_pdu_len += d_settling_samples / 8;
|
||||||
|
|
||||||
|
/* Start of burst */
|
||||||
|
add_sob (nitems_written (0));
|
||||||
|
}
|
||||||
|
|
||||||
|
noutput_items = std::max (0, noutput_items);
|
||||||
|
min_available = std::min ((size_t) noutput_items,
|
||||||
|
(d_pdu_len - d_encoded) * 8);
|
||||||
|
|
||||||
|
memcpy (out, d_pdu_encoded + d_encoded * 8,
|
||||||
|
min_available * sizeof(float));
|
||||||
|
d_encoded += min_available / 8;
|
||||||
|
|
||||||
|
/* End of the frame reached */
|
||||||
|
if (d_encoded == d_pdu_len) {
|
||||||
|
add_eob (nitems_written (0) + min_available - 1);
|
||||||
|
d_encoded = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return min_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
upsat_fsk_frame_encoder_impl::work (int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items)
|
||||||
|
{
|
||||||
|
float *out = (float *) output_items[0];
|
||||||
|
|
||||||
|
if(d_is_ax25) {
|
||||||
|
return ax25_frame_handling(out, noutput_items);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return raw_frame_handling(out, noutput_items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace satnogs */
|
} /* namespace satnogs */
|
||||||
} /* namespace gr */
|
} /* namespace gr */
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <satnogs/upsat_fsk_frame_encoder.h>
|
#include <satnogs/upsat_fsk_frame_encoder.h>
|
||||||
#include <satnogs/whitening.h>
|
#include <satnogs/whitening.h>
|
||||||
|
#include <satnogs/ax25.h>
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
{
|
{
|
||||||
|
@ -47,6 +48,10 @@ namespace gr
|
||||||
size_t d_pdu_len;
|
size_t d_pdu_len;
|
||||||
whitening d_scrambler;
|
whitening d_scrambler;
|
||||||
uint8_t *d_pdu;
|
uint8_t *d_pdu;
|
||||||
|
uint8_t *d_ax25_pdu;
|
||||||
|
uint8_t *d_ax25_tmp_buf;
|
||||||
|
uint8_t *d_ax25_addr;
|
||||||
|
size_t d_ax25_addr_len;
|
||||||
float *d_pdu_encoded;
|
float *d_pdu_encoded;
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -58,6 +63,11 @@ namespace gr
|
||||||
inline void
|
inline void
|
||||||
add_eob (uint64_t item);
|
add_eob (uint64_t item);
|
||||||
|
|
||||||
|
inline int
|
||||||
|
raw_frame_handling(float *out, int noutput_items);
|
||||||
|
inline int
|
||||||
|
ax25_frame_handling(float *out, int noutput_items);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
upsat_fsk_frame_encoder_impl (const std::vector<uint8_t>& preamble,
|
upsat_fsk_frame_encoder_impl (const std::vector<uint8_t>& preamble,
|
||||||
const std::vector<uint8_t>& sync_word,
|
const std::vector<uint8_t>& sync_word,
|
||||||
|
@ -65,6 +75,10 @@ namespace gr
|
||||||
bool manchester,
|
bool manchester,
|
||||||
bool msb_first,
|
bool msb_first,
|
||||||
bool ax25_format,
|
bool ax25_format,
|
||||||
|
const std::string& ax25_dest_addr,
|
||||||
|
uint8_t ax25_dest_ssid,
|
||||||
|
const std::string& ax25_src_addr,
|
||||||
|
uint8_t ax25_src_ssid,
|
||||||
size_t settling_samples);
|
size_t settling_samples);
|
||||||
~upsat_fsk_frame_encoder_impl ();
|
~upsat_fsk_frame_encoder_impl ();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue