diff --git a/CMakeLists.txt b/CMakeLists.txt index c5eeb03..b3e50e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ enable_testing() # Enable C++11 support set (CMAKE_CXX_STANDARD 11) add_definitions(-std=c++11) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") #select the release build type by default to get optimization flags if(NOT CMAKE_BUILD_TYPE) diff --git a/examples/morse_decoding_goliat.grc b/examples/morse_decoding_goliat.grc index 3644101..0f8fc0d 100644 --- a/examples/morse_decoding_goliat.grc +++ b/examples/morse_decoding_goliat.grc @@ -458,11 +458,11 @@ of a full period of the CW signal with frequency freq. _enabled - 0 + 1 _coordinate - (1152, 276) + (936, 212) _rotation @@ -1662,7 +1662,7 @@ of a full period of the CW signal with frequency freq. _coordinate - (488, 580) + (584, 588) _rotation @@ -1703,6 +1703,12 @@ of a full period of the CW signal with frequency freq. 0 1 + + blocks_add_xx_0 + audio_sink_0 + 0 + 0 + blocks_add_xx_0 blocks_throttle_0 diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 5dcfbd0..94d4e32 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -29,5 +29,7 @@ install(FILES satnogs_udp_msg_source.xml satnogs_debug_msg_source.xml satnogs_json_to_ecss_src.xml - satnogs_tcp_rigctl_msg_source.xml DESTINATION share/gnuradio/grc/blocks + satnogs_tcp_rigctl_msg_source.xml + satnogs_frame_encoder.xml + satnogs_doppler_correction_cc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/CMakeLists.txt.orig b/grc/CMakeLists.txt.orig new file mode 100644 index 0000000..a6de106 --- /dev/null +++ b/grc/CMakeLists.txt.orig @@ -0,0 +1,39 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +install(FILES + satnogs_cw_matched_filter_ff.xml + satnogs_morse_decoder.xml + satnogs_morse_debug_source.xml + satnogs_clear_text_msg_sink.xml + satnogs_cw_to_symbol.xml + satnogs_afsk_decoder.xml + satnogs_sine_matched_filter_ff.xml + satnogs_ax25_encoder_bf.xml + satnogs_ax25_decoder_b.xml + satnogs_udp_msg_source.xml + satnogs_debug_msg_source.xml +<<<<<<< HEAD + satnogs_json_to_ecss_src.xml + satnogs_tcp_rigctl_msg_source.xml DESTINATION share/gnuradio/grc/blocks +======= + satnogs_tcp_rigctl_msg_source.xml + satnogs_frame_encoder.xml + satnogs_doppler_correction_cc.xml DESTINATION share/gnuradio/grc/blocks +>>>>>>> 82c9ff2850235a69206a1fb2db3a9f039608a6f6 +) diff --git a/grc/satnogs_doppler_correction_cc.xml b/grc/satnogs_doppler_correction_cc.xml new file mode 100644 index 0000000..63840f8 --- /dev/null +++ b/grc/satnogs_doppler_correction_cc.xml @@ -0,0 +1,49 @@ + + + Doppler Correction + satnogs_doppler_correction_cc + satnogs + import satnogs + satnogs.doppler_correction_cc($target_freq, $sampling_rate, $corrections_per_sec) + + + Target Frequency + target_freq + real + + + + Sample Rate + sampling_rate + samp_rate + real + + + + Corrections per Second + corrections_per_sec + 1000 + int + + + + freq + message + + + + reset + message + 1 + + + + in + complex + + + + out + complex + + diff --git a/grc/satnogs_frame_encoder.xml b/grc/satnogs_frame_encoder.xml new file mode 100644 index 0000000..f628dd9 --- /dev/null +++ b/grc/satnogs_frame_encoder.xml @@ -0,0 +1,38 @@ + + + frame_encoder + satnogs_frame_encoder + satnogs + import satnogs + satnogs.frame_encoder($append_preamble, $ecss_encap, $dest_addr, $dest_ssid, $src_addr, $src_ssid) + + + ... + ... + ... + + + + + in + + + + + + out + + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index c8bd087..104307a 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -40,6 +40,9 @@ install(FILES udp_msg_source.h debug_msg_source.h json_to_ecss_src.h - tc_tm.h - tcp_rigctl_msg_source.h DESTINATION include/satnogs + tcp_rigctl_msg_source.h + frame_encoder.h + doppler_correction_cc.h + doppler_fit.h + freq_drift.h DESTINATION include/satnogs ) diff --git a/include/satnogs/CMakeLists.txt.orig b/include/satnogs/CMakeLists.txt.orig new file mode 100644 index 0000000..0875275 --- /dev/null +++ b/include/satnogs/CMakeLists.txt.orig @@ -0,0 +1,53 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install public header files +######################################################################## +install(FILES + api.h + ax25.h + config.h + cw_matched_filter_ff.h + log.h + morse_tree.h + morse.h + morse_decoder.h + morse_debug_source.h + clear_text_msg_sink.h + cw_to_symbol.h + afsk_decoder.h + sine_matched_filter_ff.h + utils.h + ax25_encoder_bf.h + ax25_decoder_b.h + udp_msg_source.h + debug_msg_source.h +<<<<<<< HEAD + json_to_ecss_src.h + tc_tm.h + tcp_rigctl_msg_source.h DESTINATION include/satnogs +======= + tcp_rigctl_msg_source.h + frame_encoder.h + doppler_correction_cc.h + doppler_fit.h + freq_drift.h DESTINATION include/satnogs +>>>>>>> 82c9ff2850235a69206a1fb2db3a9f039608a6f6 +) diff --git a/include/satnogs/doppler_correction_cc.h b/include/satnogs/doppler_correction_cc.h new file mode 100644 index 0000000..3f130f5 --- /dev/null +++ b/include/satnogs/doppler_correction_cc.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_H +#define INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief This block corrects the doppler effect between the ground + * station and the satellite. It takes the imput stream in baseband + * and applies proper corrections to keep the carrier at the desired + * frequency. To achieve that it uses messages containing the absolute + * predicted frequency of the satellite from software like Gpredict. + * + * \ingroup satnogs + * + */ + class SATNOGS_API doppler_correction_cc : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * The doppler correction block. The input is the complex signal at + * baseband as it comes from the SDR device. The message input \p freq + * received periodically messages containing the predicted absolute + * frequency of the satellite at the moment of the + * @param target_freq the absolute frequency of the satellite + * @param sampling_rate the sampling rate of the signal + * @param corrections_per_sec the number of the corrections every second + * that the block should perform + */ + static sptr + make (double target_freq, double sampling_rate, + size_t corrections_per_sec = 1000); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_H */ + diff --git a/include/satnogs/doppler_fit.h b/include/satnogs/doppler_fit.h new file mode 100644 index 0000000..a9f9a3b --- /dev/null +++ b/include/satnogs/doppler_fit.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_DOPPLER_FIT_H +#define INCLUDED_SATNOGS_DOPPLER_FIT_H + +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Doppler frequency polynomial fitting tool + * \ingroup satnogs + */ + class SATNOGS_API doppler_fit + { + public: + doppler_fit (size_t degree); + + void + fit (std::deque drifts); + + void + predict_freqs (double *freqs, size_t ncorrections, + size_t samples_per_correction); + + private: + const size_t d_degree; + double d_last_x; + std::vector d_coeff; + boost::mutex d_mutex; + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_DOPPLER_FIT_H */ + diff --git a/include/satnogs/frame_encoder.h b/include/satnogs/frame_encoder.h new file mode 100644 index 0000000..82582ca --- /dev/null +++ b/include/satnogs/frame_encoder.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_FRAME_ENCODER_H +#define INCLUDED_SATNOGS_FRAME_ENCODER_H + +#include +#include + +namespace gr { + namespace satnogs { + + /*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ + class SATNOGS_API frame_encoder : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of satnogs::frame_encoder. + * + * To avoid accidental use of raw pointers, satnogs::frame_encoder's + * constructor is in a private implementation + * class. satnogs::frame_encoder::make is the public interface for + * creating new instances. + */ + static sptr make(bool append_preamble, bool ecss_encap, const std::string& dest_addr, uint8_t dest_ssid, const std::string& src_addr, uint8_t src_ssid); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_FRAME_ENCODER_H */ + diff --git a/include/satnogs/freq_drift.h b/include/satnogs/freq_drift.h new file mode 100644 index 0000000..f5edd19 --- /dev/null +++ b/include/satnogs/freq_drift.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_FREQ_DRIFT_H +#define INCLUDED_SATNOGS_FREQ_DRIFT_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Class that specifies the frequency drift at a given time. + * The time is measured in samples. + * \ingroup satnogs + */ + class SATNOGS_API freq_drift + { + public: + freq_drift (uint64_t x, double y); + ~freq_drift (); + double + get_freq_drift () const; + void + set_freq_drift (double freqDrift); + uint64_t + get_x () const; + void + set_x (uint64_t x); + + private: + uint64_t d_x; + double d_freq_drift; + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_FREQ_DRIFT_H */ + diff --git a/include/satnogs/tc_tm.h b/include/satnogs/tc_tm.h index 4227b5d..2d67b94 100644 --- a/include/satnogs/tc_tm.h +++ b/include/satnogs/tc_tm.h @@ -179,17 +179,17 @@ namespace gr uint16_t crc; /* CRC or checksum, mission specific*/ } tc_tm_pkt; - /* - extern const uint8_t services_verification_TC_TM[MAX_SERVICES][MAX_SUBTYPES][2]; - extern const uint8_t app_id_verification[MAX_APP_ID]; - extern const uint8_t services_verification_OBC_TC[MAX_SERVICES][MAX_SUBTYPES]; + + const uint8_t services_verification_TC_TM[MAX_SERVICES][MAX_SUBTYPES][2]; + const uint8_t app_id_verification[MAX_APP_ID]; + const uint8_t services_verification_OBC_TC[MAX_SERVICES][MAX_SUBTYPES]; extern OBC_ret_state_t verification_pack_pkt_api (uint8_t *buf, tc_tm_pkt *pkt, uint16_t *buf_pointer); extern OBC_ret_state_t hk_pack_pkt_api (uint8_t *buf, tc_tm_pkt *pkt, uint16_t *buf_pointer); - */ + static inline uint8_t ecss_tm_checksum (const uint8_t *data, uint16_t size) @@ -211,7 +211,7 @@ namespace gr uint8_t ver, dfield_hdr, ccsds_sec_hdr, tc_pus; tmp_crc[0] = buf[size - 1]; - tmp_crc[1] = checkSum (buf, size - 2); + tmp_crc[1] = ecss_tm_checksum (buf, size - 2); ver = buf[0] >> 5; @@ -366,7 +366,7 @@ namespace gr buf[4] = cnv.cnv8[0]; buf[5] = cnv.cnv8[1]; - buf[buf_pointer] = checkSum (buf, buf_pointer - 1); + buf[buf_pointer] = ecss_tm_checksum (buf, buf_pointer - 1); *size = buf_pointer; return R_OBC_OK; } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 44c6902..b3026a7 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -39,6 +39,10 @@ list(APPEND satnogs_sources debug_msg_source_impl.cc tcp_rigctl_msg_source_impl.cc json_to_ecss_src_impl.cc ) + doppler_correction_cc_impl.cc + frame_encoder_impl.cc + doppler_fit.cc + freq_drift.cc ) set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE) if(NOT satnogs_sources) diff --git a/lib/CMakeLists.txt.orig b/lib/CMakeLists.txt.orig new file mode 100644 index 0000000..d9ffcde --- /dev/null +++ b/lib/CMakeLists.txt.orig @@ -0,0 +1,101 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup library +######################################################################## +include(GrPlatform) #define LIB_SUFFIX + +include_directories(${Boost_INCLUDE_DIR}) +link_directories(${Boost_LIBRARY_DIRS}) +list(APPEND satnogs_sources + cw_matched_filter_ff_impl.cc + morse_tree.cc + morse_decoder_impl.cc + morse_debug_source_impl.cc + clear_text_msg_sink_impl.cc + cw_to_symbol_impl.cc + afsk_decoder_impl.cc + sine_matched_filter_ff_impl.cc + ax25_encoder_bf_impl.cc + ax25_decoder_b_impl.cc + udp_msg_source_impl.cc + debug_msg_source_impl.cc + tcp_rigctl_msg_source_impl.cc +<<<<<<< HEAD + json_to_ecss_src_impl.cc ) +======= + doppler_correction_cc_impl.cc + frame_encoder_impl.cc + doppler_fit.cc + freq_drift.cc ) +>>>>>>> 82c9ff2850235a69206a1fb2db3a9f039608a6f6 + +set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE) +if(NOT satnogs_sources) + MESSAGE(STATUS "No C++ sources... skipping lib/") + return() +endif(NOT satnogs_sources) + +add_library(gnuradio-satnogs SHARED ${satnogs_sources}) +target_link_libraries(gnuradio-satnogs + ${Boost_LIBRARIES} + ${GNURADIO_ALL_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT}) + +set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") + +if(APPLE) + set_target_properties(gnuradio-satnogs PROPERTIES + INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" + ) +endif(APPLE) + +######################################################################## +# Install built library files +######################################################################## +install(TARGETS gnuradio-satnogs + LIBRARY DESTINATION lib${LIB_SUFFIX} # .so/.dylib file + ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file + RUNTIME DESTINATION bin # .dll file +) + +######################################################################## +# Build and register unit test +######################################################################## +include(GrTest) + +#include_directories(${CPPUNIT_INCLUDE_DIRS}) + +#list(APPEND test_satnogs_sources +# ${CMAKE_CURRENT_SOURCE_DIR}/test_satnogs.cc +# ${CMAKE_CURRENT_SOURCE_DIR}/qa_satnogs.cc +#) + +#add_executable(test-satnogs ${test_satnogs_sources}) + +#target_link_libraries( +# test-satnogs +# ${GNURADIO_RUNTIME_LIBRARIES} +# ${Boost_LIBRARIES} +# ${CPPUNIT_LIBRARIES} +# gnuradio-satnogs +#) + +#GR_ADD_TEST(test_satnogs test-satnogs) diff --git a/lib/doppler_correction_cc_impl.cc b/lib/doppler_correction_cc_impl.cc new file mode 100644 index 0000000..2d1525b --- /dev/null +++ b/lib/doppler_correction_cc_impl.cc @@ -0,0 +1,215 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "doppler_correction_cc_impl.h" +#include +#include + +namespace gr +{ + namespace satnogs + { + + doppler_correction_cc::sptr + doppler_correction_cc::make (double target_freq, double sampling_rate, + size_t corrections_per_sec) + { + return gnuradio::get_initial_sptr ( + new doppler_correction_cc_impl (target_freq, sampling_rate, + corrections_per_sec)); + } + + /* + * The private constructor + */ + doppler_correction_cc_impl::doppler_correction_cc_impl ( + double target_freq, double sampling_rate, size_t corrections_per_sec) : + gr::sync_block ("doppler_correction_cc", + gr::io_signature::make (1, 1, sizeof(gr_complex)), + gr::io_signature::make (1, 1, sizeof(gr_complex))), + d_target_freq (target_freq), + d_samp_rate (sampling_rate), + d_update_period (sampling_rate / (double) corrections_per_sec), + d_est_thrhld (7), + d_corrections_per_sec (corrections_per_sec), + d_nco (), + /* A 3-rd order polynomial curve fitting is more than enough */ + d_doppler_fit_engine (3), + d_freq_diff (0.0), + d_have_est (false), + d_freq_est_num (0), + d_corrections (0), + d_corrected_samples (0) + { + message_port_register_in (pmt::mp ("freq")); + message_port_register_in (pmt::mp ("reset")); + + /* + * NOTE: + * Set the maximum number of samples to be equivalent of half a second. + * With this way we are sure that at least one frequency message + * per second will be processed. + * + * This is taken into consideration due to the fact that the work() + * and the input message handler are NOT reentrant. + */ + set_max_noutput_items (d_samp_rate / 2.0); + set_alignment (8); + + set_msg_handler ( + pmt::mp ("freq"), + boost::bind (&doppler_correction_cc_impl::new_freq, this, _1)); + set_msg_handler ( + pmt::mp ("reset"), + boost::bind (&doppler_correction_cc_impl::reset, this, _1)); + + /* Allocate the buffer that will hold the predicted frequency differences */ + d_predicted_freqs = new double[d_corrections_per_sec]; + + /* Allocate aligned memory for the NCO */ + d_nco_buff = (gr_complex *) volk_malloc ( + d_update_period * sizeof(gr_complex), 32); + if (!d_nco_buff) { + throw std::runtime_error ("Could not allocate NCO memory"); + } + } + + void + doppler_correction_cc_impl::new_freq (pmt::pmt_t msg) + { + boost::mutex::scoped_lock lock (d_mutex); + double new_freq; + new_freq = pmt::to_double (msg); + d_freq_diff = d_target_freq - new_freq; + if (!d_have_est) { + d_freq_est_num++; + d_doppler_freqs.push_back ( + freq_drift (nitems_written (0), d_freq_diff)); + if (d_freq_est_num > d_est_thrhld - 1) { + d_doppler_fit_engine.fit (d_doppler_freqs); + d_doppler_fit_engine.predict_freqs (d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_have_est = true; + } + } + else { + d_doppler_freqs.pop_front (); + d_doppler_freqs.push_back ( + freq_drift (nitems_written (0), d_freq_diff)); + + /* Fit the doppler drift based on the new estimated frequency */ + d_doppler_fit_engine.fit (d_doppler_freqs); + /* Predict the frequency differences for the near future */ + d_doppler_fit_engine.predict_freqs (d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_corrections = 0; + } + } + + void + doppler_correction_cc_impl::reset (pmt::pmt_t msg) + { + boost::mutex::scoped_lock lock (d_mutex); + d_doppler_freqs.clear (); + d_freq_est_num = 0; + d_corrections = 0; + d_have_est = false; + } + + /* + * Our virtual destructor. + */ + doppler_correction_cc_impl::~doppler_correction_cc_impl () + { + delete[] d_predicted_freqs; + volk_free (d_nco_buff); + } + + int + doppler_correction_cc_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + int produced = 0; + size_t cnt; + + /* + * If we do not have an estimation yet, just copy the input to the output. + * Otherwise perform Doppler correction, using the fitted curve indicating + * the frequency drift. + */ + if (d_have_est) { + while (produced < noutput_items) { + /* + * If no samples have been corrected from the current correction step + * compute and store the NCO buffer with the corresponding frequency + */ + if (d_corrected_samples == 0) { + d_nco.set_freq ( + 2 * M_PI * (-d_predicted_freqs[d_corrections]) / d_samp_rate); + d_nco.sincos (d_nco_buff, d_update_period, 1.0); + d_corrections++; + + /* + * The doppler estimation may fail/delay. In such a case the block + * should continue using the predicted frequencies + */ + if (d_corrections == d_corrections_per_sec) { + d_doppler_fit_engine.predict_freqs (d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_corrections = 0; + } + } + + cnt = std::min (d_update_period - d_corrected_samples, + (size_t) (noutput_items - produced)); + /* Perform the doppler shift correction */ + volk_32fc_x2_multiply_32fc (out + produced, in + produced, + d_nco_buff + d_corrected_samples, cnt); + + /* Make the proper advances */ + produced += (int) cnt; + d_corrected_samples += cnt; + + if (d_corrected_samples == d_update_period) { + d_corrected_samples = 0; + } + } + } + else { + memcpy (out, in, noutput_items * sizeof(gr_complex)); + } + + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/doppler_correction_cc_impl.h b/lib/doppler_correction_cc_impl.h new file mode 100644 index 0000000..4cca6dc --- /dev/null +++ b/lib/doppler_correction_cc_impl.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_IMPL_H +#define INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_IMPL_H + +#include +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + class doppler_correction_cc_impl : public doppler_correction_cc + { + private: + const double d_target_freq; + const double d_samp_rate; + const size_t d_update_period; + const size_t d_est_thrhld; + const size_t d_corrections_per_sec; + + gr::fxpt_nco d_nco; + doppler_fit d_doppler_fit_engine; + double d_freq_diff; + bool d_have_est; + size_t d_freq_est_num; + size_t d_corrections; + size_t d_corrected_samples; + std::deque d_doppler_freqs; + double *d_predicted_freqs; + gr_complex *d_nco_buff; + boost::mutex d_mutex; + + void + new_freq (pmt::pmt_t msg); + + void + reset (pmt::pmt_t msg); + + public: + doppler_correction_cc_impl (double target_freq, double sampling_rate, + size_t corrections_per_sec); + ~doppler_correction_cc_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); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_IMPL_H */ + diff --git a/lib/doppler_fit.cc b/lib/doppler_fit.cc new file mode 100644 index 0000000..76a3a94 --- /dev/null +++ b/lib/doppler_fit.cc @@ -0,0 +1,145 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + /** + * Creates a polynomial fitting routine. + * @param degree the degree of the polynomial + */ + doppler_fit::doppler_fit (size_t degree) : + d_degree(degree), + d_last_x(0.0) + { + } + + /** + * This method calculates the coefficients of the polynomial that will + * be used by the predict_freqs() method to produce simulated frequency + * differences + * @param drifts the queue containing the frequency differences and the + * corresponding timings that these frequencies diffrences occured. Time is + * measured in samples since the start of the flowgraph execution. + */ + void + doppler_fit::fit (std::deque drifts) + { + size_t i; + size_t j; + size_t s; + size_t singular; + double val; + s = drifts.size(); + + boost::numeric::ublas::matrix x_matrix(s, d_degree+1); + boost::numeric::ublas::matrix y_matrix(s, 1); + + for(i = 0; i < s; i++){ + y_matrix(i, 0) = drifts[i].get_freq_drift(); + } + + for(i = 0; i < s; i++){ + val = 1.0; + for(j = 0; j < d_degree + 1; j++) { + x_matrix(i, j) = val; + val *= drifts[i].get_x(); + } + } + + /* Transpose the matrix with the x values */ + boost::numeric::ublas::matrix tx_matrix ( + boost::numeric::ublas::trans (x_matrix)); + + boost::numeric::ublas::matrix txx_matrix ( + boost::numeric::ublas::prec_prod(tx_matrix, x_matrix)); + + boost::numeric::ublas::matrix txy_matrix ( + boost::numeric::ublas::prec_prod(tx_matrix, y_matrix)); + + boost::numeric::ublas::permutation_matrix perm(txx_matrix.size1()); + singular = boost::numeric::ublas::lu_factorize(txx_matrix, perm); + BOOST_ASSERT( singular == 0 ); + + boost::numeric::ublas::lu_substitute(txx_matrix, perm, txy_matrix); + + /* + * Lock the mutex to make sure that no one uses at the same time the + * coefficients + */ + boost::mutex::scoped_lock lock(d_mutex); + d_coeff = std::vector (txy_matrix.data().begin(), + txy_matrix.data().end()); + d_last_x = drifts[s - 1].get_x(); + } + + /** + * Creates a number of frequency differences predictions using polynomial + * curve fitting. + * @param freqs buffer that will hold the predicted frequency differences. + * It is responsibility of the caller to provide enough memory for at most + * \p ncorrections double numbers. + * @param ncorrections the number predicted frequencies that the method + * will produce. + * @param samples_per_correction the number of samples elapsed between each + * correction. + */ + void + doppler_fit::predict_freqs (double *freqs, size_t ncorrections, + size_t samples_per_correction) + { + size_t i; + size_t j; + double predicted_freq_diff; + double x; + double xT; + boost::mutex::scoped_lock lock(d_mutex); + for(i = 0; i < ncorrections; i++){ + predicted_freq_diff = 0.0; + xT = 1.0; + x = d_last_x + i * samples_per_correction; + for(j = 0; j < d_degree + 1; j++){ + predicted_freq_diff += d_coeff[j] * xT; + xT *= x; + } + freqs[i] = predicted_freq_diff; + } + + /* + * The predict method can be called multiple times without update the + * fitness of the polynomial. For this reason we alter the last x + */ + d_last_x = d_last_x + (ncorrections + 1) * samples_per_correction; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/frame_encoder_impl.cc b/lib/frame_encoder_impl.cc new file mode 100644 index 0000000..4c52252 --- /dev/null +++ b/lib/frame_encoder_impl.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "frame_encoder_impl.h" + +namespace gr +{ + namespace satnogs + { + + frame_encoder::sptr + frame_encoder::make (bool append_preamble, bool ecss_encap, + const std::string& dest_addr, uint8_t dest_ssid, + const std::string& src_addr, uint8_t src_ssid) + { + return gnuradio::get_initial_sptr ( + new frame_encoder_impl (append_preamble, ecss_encap, dest_addr, + dest_ssid, src_addr, src_ssid)); + } + + /* + * The private constructor + */ + frame_encoder_impl::frame_encoder_impl (bool append_preamble, + bool ecss_encap, + const std::string& dest_addr, + uint8_t dest_ssid, + const std::string& src_addr, + uint8_t src_ssid) : + gr::sync_block ("frame_encoder", gr::io_signature::make (0, 0, 0), + gr::io_signature::make (0, 0, 0)) + { + } + + /* + * Our virtual destructor. + */ + frame_encoder_impl::~frame_encoder_impl () + { + } + + int + frame_encoder_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + // Do <+signal processing+> + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/frame_encoder_impl.h b/lib/frame_encoder_impl.h new file mode 100644 index 0000000..1cd079a --- /dev/null +++ b/lib/frame_encoder_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDED_SATNOGS_FRAME_ENCODER_IMPL_H +#define INCLUDED_SATNOGS_FRAME_ENCODER_IMPL_H + +#include + +namespace gr +{ + namespace satnogs + { + + class frame_encoder_impl : public frame_encoder + { + private: + // Nothing to declare in this block. + + public: + frame_encoder_impl (bool append_preamble, bool ecss_encap, + const std::string& dest_addr, uint8_t dest_ssid, + const std::string& src_addr, uint8_t src_ssid); + ~frame_encoder_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); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_FRAME_ENCODER_IMPL_H */ + diff --git a/lib/freq_drift.cc b/lib/freq_drift.cc new file mode 100644 index 0000000..e755734 --- /dev/null +++ b/lib/freq_drift.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, Libre Space Foundation + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +namespace gr +{ + namespace satnogs + { + + freq_drift::freq_drift (uint64_t x, double y) : + d_x (x), + d_freq_drift (y) + { + } + + freq_drift::~freq_drift () + { + } + + double + freq_drift::get_freq_drift () const + { + return d_freq_drift; + } + + void + freq_drift::set_freq_drift (double freq_drift) + { + d_freq_drift = freq_drift; + } + + uint64_t + freq_drift::get_x () const + { + return d_x; + } + + void + freq_drift::set_x (uint64_t x) + { + d_x = x; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/tcp_rigctl_msg_source_impl.cc b/lib/tcp_rigctl_msg_source_impl.cc index bbd705e..12d3670 100644 --- a/lib/tcp_rigctl_msg_source_impl.cc +++ b/lib/tcp_rigctl_msg_source_impl.cc @@ -34,6 +34,10 @@ #include #include #include +#include +#include +#include + namespace gr { @@ -68,6 +72,22 @@ namespace gr this))); } + static inline void + send_freq(int sock, uint64_t freq) + { + static char buf[512]; + snprintf(buf, 512, "%llu\n", freq); + send(sock, buf, strnlen(buf, 512), 0); + } + + static inline void + send_report_code(int sock, int code) + { + static char buf[512]; + snprintf(buf, 512, "RPRT %d\n", code); + send(sock, buf, strnlen(buf, 512), 0); + } + void tcp_rigctl_msg_source_impl::tcp_msg_accepter () { @@ -78,7 +98,10 @@ namespace gr socklen_t client_addr_len; ssize_t ret; uint8_t *buf; - double freq; + double freq = 0.0; + uint64_t reported_freq = 0; + int error_code = 0; + int optval = 1; if ((listen_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror ("opening UDP socket"); @@ -120,7 +143,13 @@ namespace gr exit (EXIT_FAILURE); } - while ((ret = recv (sock, buf, d_mtu, 0)) > 0) { + /* Apply the TCP_NODELAY option at the accepted socket */ + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) < 0){ + perror ("TCP setsockopt"); + exit (EXIT_FAILURE); + } + + while ((ret = recv (sock, buf, d_mtu, 0)) > 0 && d_running) { switch (buf[0]) { case 'F': @@ -135,11 +164,27 @@ namespace gr * the in-equality agains 0.0. */ if (freq != 0.0) { + reported_freq = freq; message_port_pub (pmt::mp ("freq"), pmt::from_double (freq)); + error_code = 0; } + else{ + error_code = -11; + } + /* Send the report code */ + send_report_code(sock, error_code); + break; + case 'f': + send_freq(sock, reported_freq); + break; + /* Terminate the connection and exit */ + case 'q': + send_report_code(sock, 0); + d_running = false; break; default: LOG_WARN("Unsupported rigctl command"); + send_report_code(sock, -11); } } shutdown (sock, SHUT_RDWR); diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index 61c4016..2b40315 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -23,6 +23,8 @@ #include "satnogs/debug_msg_source.h" #include "satnogs/tcp_rigctl_msg_source.h" #include "satnogs/json_to_ecss_src.h" +#include "satnogs/doppler_correction_cc.h" +#include "satnogs/frame_encoder.h" %} @@ -53,3 +55,7 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source); GR_SWIG_BLOCK_MAGIC2(satnogs, tcp_rigctl_msg_source); %include "satnogs/json_to_ecss_src.h" GR_SWIG_BLOCK_MAGIC2(satnogs, json_to_ecss_src); +%include "satnogs/frame_encoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, frame_encoder); +%include "satnogs/doppler_correction_cc.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, doppler_correction_cc); diff --git a/swig/satnogs_swig.i.orig b/swig/satnogs_swig.i.orig new file mode 100644 index 0000000..1988c68 --- /dev/null +++ b/swig/satnogs_swig.i.orig @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ + +#define SATNOGS_API + +%include +%include "gnuradio.i" // the common stuff + +//load generated python docstrings +%include "satnogs_swig_doc.i" + +%{ +#include "satnogs/cw_matched_filter_ff.h" +#include "satnogs/morse_tree.h" +#include "satnogs/morse_decoder.h" +#include "satnogs/morse_debug_source.h" +#include "satnogs/clear_text_msg_sink.h" +#include "satnogs/cw_to_symbol.h" +#include "satnogs/afsk_decoder.h" +#include "satnogs/sine_matched_filter_ff.h" +#include "satnogs/ax25_encoder_bf.h" +#include "satnogs/ax25_decoder_b.h" +#include "satnogs/udp_msg_source.h" +#include "satnogs/debug_msg_source.h" +#include "satnogs/tcp_rigctl_msg_source.h" +<<<<<<< HEAD +#include "satnogs/json_to_ecss_src.h" +======= +#include "satnogs/doppler_correction_cc.h" +#include "satnogs/frame_encoder.h" +>>>>>>> 82c9ff2850235a69206a1fb2db3a9f039608a6f6 +%} + + +%include "satnogs/cw_matched_filter_ff.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, cw_matched_filter_ff); +%include "satnogs/morse_tree.h" +%include "satnogs/morse_decoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder); +%include "satnogs/morse_debug_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, morse_debug_source); +%include "satnogs/clear_text_msg_sink.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, clear_text_msg_sink); +%include "satnogs/cw_to_symbol.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, cw_to_symbol); +%include "satnogs/afsk_decoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, afsk_decoder); +%include "satnogs/sine_matched_filter_ff.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, sine_matched_filter_ff); +%include "satnogs/ax25_encoder_bf.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ax25_encoder_bf); +%include "satnogs/ax25_decoder_b.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ax25_decoder_b); +%include "satnogs/udp_msg_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, udp_msg_source); +%include "satnogs/debug_msg_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source); +%include "satnogs/tcp_rigctl_msg_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, tcp_rigctl_msg_source); +<<<<<<< HEAD +%include "satnogs/json_to_ecss_src.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, json_to_ecss_src); +======= +%include "satnogs/frame_encoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, frame_encoder); +%include "satnogs/doppler_correction_cc.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, doppler_correction_cc); +>>>>>>> 82c9ff2850235a69206a1fb2db3a9f039608a6f6