diff --git a/grc/satnogs_upsat_fsk_frame_acquisition.xml b/grc/satnogs_upsat_fsk_frame_acquisition.xml index f06b07e..9e4e83b 100644 --- a/grc/satnogs_upsat_fsk_frame_acquisition.xml +++ b/grc/satnogs_upsat_fsk_frame_acquisition.xml @@ -4,7 +4,7 @@ satnogs_upsat_fsk_frame_acquisition satnogs import satnogs - satnogs.upsat_fsk_frame_acquisition($preamble, $sync_word, $whitening, $manchester, $check_crc) + satnogs.upsat_fsk_frame_acquisition($preamble, $sync_word, $whitening, $manchester, $check_crc, $ax_25) Frame Preamble @@ -60,6 +60,20 @@ + + Use AX.25 encapsulation + ax_25 + enum + + + + in float diff --git a/grc/satnogs_upsat_fsk_frame_encoder.xml b/grc/satnogs_upsat_fsk_frame_encoder.xml index 95bef59..9d5369c 100644 --- a/grc/satnogs_upsat_fsk_frame_encoder.xml +++ b/grc/satnogs_upsat_fsk_frame_encoder.xml @@ -4,7 +4,7 @@ satnogs_upsat_fsk_frame_encoder satnogs import satnogs - satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester, $msb_first, $settling_samples) + satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester, $msb_first, $ax_25, $settling_samples) Frame Preamble @@ -74,6 +74,20 @@ + + Use AX.25 encapsulation + ax_25 + enum + + + + Number of zero settling samples settling_samples diff --git a/include/satnogs/ax25.h b/include/satnogs/ax25.h index 5d46fc2..e0c3f3a 100644 --- a/include/satnogs/ax25.h +++ b/include/satnogs/ax25.h @@ -36,6 +36,7 @@ namespace gr const uint8_t AX25_SYNC_FLAG = 0x7E; const uint8_t AX25_CALLSIGN_MAX_LEN = 6; const float AX25_SYNC_FLAG_MAP[8] = {-1, 1, 1, 1, 1, 1, 1, -1}; + const uint8_t AX25_SYNC_FLAG_MAP_BIN[8] = {0, 1, 1, 1, 1, 1, 1, 0}; /** * AX.25 Frame types */ @@ -80,7 +81,7 @@ namespace gr } /** - * Createst the header field of the AX.25 frame + * Creates the header field of the AX.25 frame * @param out the output buffer with enough memory to hold the address field * @param dest_addr the destination callsign address * @param dest_ssid the destination SSID @@ -172,9 +173,27 @@ namespace gr return i; } + /** + * Constructs an AX.25 by performing NRZ encoding and bit stuffing + * @param out the output buffer to hold the frame. Note that due to + * the NRZ encoding the output would be [-1, 1]. Also the size of the + * buffer should be enough, such that the extra stuffed bits are fitting + * on the allocated space. + * + * @param out_len due to bit stuffing the output size can vary. This + * pointer will hold the resulting frame size after bit stuffing. + * + * @param buffer buffer holding the data that should be encoded. + * Note that this buffer SHOULD contain the leading and trailing + * synchronization flag, all necessary headers and the CRC. + * + * @param buffer_len the length of the input buffer. + * + * @return the resulting status of the encoding + */ static inline ax25_encode_status_t - ax25_nrz_encode(float *out, size_t *out_len, - const uint8_t *buffer, const size_t buffer_len) + ax25_nrz_bit_stuffing (float *out, size_t *out_len, const uint8_t *buffer, + const size_t buffer_len) { uint8_t bit; uint8_t prev_bit = 0; @@ -225,6 +244,77 @@ namespace gr return AX25_ENC_OK; } + /** + * Constructs an AX.25 by performing bit stuffing. + * @param out the output buffer to hold the frame. To keep it simple, + * each byte of the buffer holds only one bit. Also the size of the + * buffer should be enough, such that the extra stuffed bits are fitting + * on the allocated space. + * + * @param out_len due to bit stuffing the output size can vary. This + * pointer will hold the resulting frame size after bit stuffing. + * + * @param buffer buffer holding the data that should be encoded. + * Note that this buffer SHOULD contain the leading and trailing + * synchronization flag, all necessary headers and the CRC. + * + * @param buffer_len the length of the input buffer. + * + * @return the resulting status of the encoding + */ + static inline ax25_encode_status_t + ax25_bit_stuffing (uint8_t *out, size_t *out_len, const uint8_t *buffer, + const size_t buffer_len) + { + uint8_t bit; + uint8_t prev_bit = 0; + size_t out_idx = 0; + size_t bit_idx; + size_t cont_1 = 0; + size_t total_cont_1 = 0; + size_t i; + + /* Leading FLAG field does not need bit stuffing */ + memcpy(out, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); + out_idx = 8; + + /* Skip the leading and trailing FLAG field */ + buffer++; + for(i = 0; i < 8 * (buffer_len - 2); i++){ + bit = (buffer[i / 8] >> ( i % 8)) & 0x1; + out[out_idx++] = bit; + + /* Check if bit stuffing should be applied */ + if(bit & prev_bit){ + cont_1++; + total_cont_1++; + if(cont_1 == 4){ + out[out_idx++] = 0; + cont_1 = 0; + } + } + else{ + cont_1 = total_cont_1 = 0; + } + prev_bit = bit; + + /* + * If the total number of continuous 1's is 15 the the frame should be + * dropped + */ + if(total_cont_1 >= 14) { + return AX25_ENC_FAIL; + } + } + + /* Trailing FLAG field does not need bit stuffing */ + memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); + out_idx += 8; + + *out_len = out_idx; + return AX25_ENC_OK; + } + } // namespace satnogs } // namespace gr diff --git a/include/satnogs/upsat_fsk_frame_acquisition.h b/include/satnogs/upsat_fsk_frame_acquisition.h index a9f23fb..d8c748b 100644 --- a/include/satnogs/upsat_fsk_frame_acquisition.h +++ b/include/satnogs/upsat_fsk_frame_acquisition.h @@ -47,18 +47,28 @@ namespace gr /*! * Creates the FSK frame acquisition block for the UPSAT satellite. * @param preamble the bytes that consist the preamble of the frame + * * @param sync_word the byte synchronization word + * * @param whitening true if the transmitted data have been processed by * the whitening algorithm of the CC1120 chip. False otherwise. + * * @param manchester true if the transmitted data have been processed by * the Manchester algorithm of the CC1120 chip. False otherwise. + * * @param check_crc if set to true the decoder will push frames only if * their CRC field in correct. + * + * @param ax25_format if set to true the frame contains an AX.25 + * encoded payload. Prior producing the payload, AX.25 decoding + * will be performed. If set to false, the payload will be pushed + * as it is. */ static sptr make (const std::vector &preamble, const std::vector &sync_word, bool whitening = false, - bool manchester = false, bool check_crc = true); + bool manchester = false, bool check_crc = true, + bool ax25_format = false); }; } // namespace satnogs diff --git a/include/satnogs/upsat_fsk_frame_encoder.h b/include/satnogs/upsat_fsk_frame_encoder.h index ca8bfc5..560359c 100644 --- a/include/satnogs/upsat_fsk_frame_encoder.h +++ b/include/satnogs/upsat_fsk_frame_encoder.h @@ -64,6 +64,8 @@ namespace gr * * @param msb_first if set to true, the the treansmission starts from the * MSB of each byte. + * @param ax25_format if set to true the frame payload will be encoded + * using AX.25 encapsulation. * * @param settling_samples the number of zero samples that the encoder * should append after the end of the FSK frame. This is especially @@ -71,6 +73,7 @@ namespace gr * arbitrary in-out ratio of samples will cause the stream tags to be * delivered at the sink block out-of-sync causing the frame transmission * to terminate sooner. + * */ static sptr make (const std::vector& preamble, @@ -78,6 +81,7 @@ namespace gr bool append_crc = true, bool whitening = false, bool manchester = false, bool msb_first = true, + bool ax25_format = false, size_t settling_samples = 64); }; diff --git a/lib/ax25_encoder_bf_impl.cc b/lib/ax25_encoder_bf_impl.cc index c2d967f..4eaddbb 100644 --- a/lib/ax25_encoder_bf_impl.cc +++ b/lib/ax25_encoder_bf_impl.cc @@ -104,7 +104,7 @@ namespace gr /* 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); - status = ax25_nrz_encode(d_endoded_frame, &d_remaining, d_tmp_buf, + status = ax25_nrz_bit_stuffing(d_endoded_frame, &d_remaining, d_tmp_buf, len); if(status != AX25_ENC_OK){ LOG_ERROR("NRZ Encoding failed"); diff --git a/lib/upsat_fsk_frame_acquisition_impl.cc b/lib/upsat_fsk_frame_acquisition_impl.cc index c150e1e..229dc3a 100644 --- a/lib/upsat_fsk_frame_acquisition_impl.cc +++ b/lib/upsat_fsk_frame_acquisition_impl.cc @@ -37,11 +37,13 @@ namespace gr upsat_fsk_frame_acquisition::make (const std::vector &preamble, const std::vector &sync_word, bool whitening, bool manchester, - bool check_crc) + bool check_crc, + bool ax25_format) { return gnuradio::get_initial_sptr ( new upsat_fsk_frame_acquisition_impl (preamble, sync_word, whitening, - manchester, check_crc)); + manchester, check_crc, + ax25_format)); } /* @@ -50,7 +52,7 @@ namespace gr upsat_fsk_frame_acquisition_impl::upsat_fsk_frame_acquisition_impl ( const std::vector &preamble, const std::vector &sync_word, bool whitening, bool manchester, - bool check_crc) : + bool check_crc, bool ax25_format) : gr::sync_block ("upsat_fsk_frame_acquisition", gr::io_signature::make (1, 1, sizeof(float)), gr::io_signature::make (0, 0, 0)), @@ -68,6 +70,7 @@ namespace gr d_whitening(whitening), d_manchester(manchester), d_check_crc(check_crc), + d_is_ax25(ax25_format), d_state (SEARCHING), d_shifting_byte (0x0), d_decoded_bytes (0), diff --git a/lib/upsat_fsk_frame_acquisition_impl.h b/lib/upsat_fsk_frame_acquisition_impl.h index 750224e..def126c 100644 --- a/lib/upsat_fsk_frame_acquisition_impl.h +++ b/lib/upsat_fsk_frame_acquisition_impl.h @@ -55,6 +55,7 @@ namespace gr const bool d_whitening; const bool d_manchester; const bool d_check_crc; + const bool d_is_ax25; decoding_state_t d_state; uint8_t d_shifting_byte; size_t d_decoded_bytes; @@ -83,7 +84,8 @@ namespace gr upsat_fsk_frame_acquisition_impl (const std::vector &preamble, const std::vector &sync_word, bool whitening, bool manchester, - bool check_crc); + bool check_crc, + bool ax25_format); ~upsat_fsk_frame_acquisition_impl (); // Where all the action really happens diff --git a/lib/upsat_fsk_frame_encoder_impl.cc b/lib/upsat_fsk_frame_encoder_impl.cc index 970d9c8..d03a748 100644 --- a/lib/upsat_fsk_frame_encoder_impl.cc +++ b/lib/upsat_fsk_frame_encoder_impl.cc @@ -39,12 +39,14 @@ namespace gr bool append_crc, bool whitening, bool manchester, bool msb_first, + bool ax25_format, size_t settling_samples) { return gnuradio::get_initial_sptr ( new upsat_fsk_frame_encoder_impl (preamble, sync_word, append_crc, - whitening, manchester, msb_first, + whitening, manchester, + msb_first, ax25_format, settling_samples)); } @@ -56,6 +58,7 @@ namespace gr const std::vector& sync_word, bool append_crc, bool whitening, bool manchester, bool msb_first, + bool ax25_format, size_t settling_samples) : gr::sync_block ("upsat_fsk_frame_encoder", gr::io_signature::make (0, 0, 0), @@ -68,6 +71,7 @@ namespace gr d_whitening(whitening), d_manchester(manchester), d_msb_first(msb_first), + d_is_ax25(ax25_format), d_max_pdu_len(d_preamble_len + d_sync_word_len + sizeof(uint8_t) + UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)), d_settling_samples(settling_samples), diff --git a/lib/upsat_fsk_frame_encoder_impl.h b/lib/upsat_fsk_frame_encoder_impl.h index fe3abd2..34f3edb 100644 --- a/lib/upsat_fsk_frame_encoder_impl.h +++ b/lib/upsat_fsk_frame_encoder_impl.h @@ -40,6 +40,7 @@ namespace gr const bool d_whitening; const bool d_manchester; const bool d_msb_first; + const bool d_is_ax25; const size_t d_max_pdu_len; const size_t d_settling_samples; size_t d_encoded; @@ -63,6 +64,7 @@ namespace gr bool append_crc, bool whitening, bool manchester, bool msb_first, + bool ax25_format, size_t settling_samples); ~upsat_fsk_frame_encoder_impl ();