From 6e3d8f9c1062f8858272590046d89895ad8387c1 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 26 Aug 2016 19:49:02 +0300 Subject: [PATCH 01/26] Remove unnecessary block --- grc/CMakeLists.txt | 1 - grc/satnogs_json_to_ecss_src.xml | 19 ------- include/satnogs/CMakeLists.txt | 1 - include/satnogs/json_to_ecss_src.h | 56 ------------------ lib/CMakeLists.txt | 1 - lib/json_to_ecss_src_impl.cc | 91 ------------------------------ lib/json_to_ecss_src_impl.h | 63 --------------------- swig/satnogs_swig.i | 3 - 8 files changed, 235 deletions(-) delete mode 100644 grc/satnogs_json_to_ecss_src.xml delete mode 100644 include/satnogs/json_to_ecss_src.h delete mode 100644 lib/json_to_ecss_src_impl.cc delete mode 100644 lib/json_to_ecss_src_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 4546851..a625f6f 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -25,7 +25,6 @@ install(FILES satnogs_sine_matched_filter_ff.xml satnogs_udp_msg_source.xml satnogs_debug_msg_source.xml - satnogs_json_to_ecss_src.xml satnogs_tcp_rigctl_msg_source.xml satnogs_frame_encoder.xml satnogs_doppler_correction_cc.xml diff --git a/grc/satnogs_json_to_ecss_src.xml b/grc/satnogs_json_to_ecss_src.xml deleted file mode 100644 index 3a3e716..0000000 --- a/grc/satnogs_json_to_ecss_src.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - JSON to ECSS - satnogs_json_to_ecss_src - satnogs - import satnogs - satnogs.json_to_ecss_src() - - - - in - message - - - - out - message - - diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index c31ecee..e874d38 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -36,7 +36,6 @@ install(FILES utils.h udp_msg_source.h debug_msg_source.h - json_to_ecss_src.h tcp_rigctl_msg_source.h frame_encoder.h doppler_correction_cc.h diff --git a/include/satnogs/json_to_ecss_src.h b/include/satnogs/json_to_ecss_src.h deleted file mode 100644 index 2883b6e..0000000 --- a/include/satnogs/json_to_ecss_src.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- 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_JSON_TO_ECSS_SRC_H -#define INCLUDED_SATNOGS_JSON_TO_ECSS_SRC_H - -#include -#include - -namespace gr { - namespace satnogs { - - /*! - * \brief <+description of block+> - * \ingroup satnogs - * - */ - class SATNOGS_API json_to_ecss_src : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of satnogs::json_to_ecss_src. - * - * To avoid accidental use of raw pointers, satnogs::json_to_ecss_src's - * constructor is in a private implementation - * class. satnogs::json_to_ecss_src::make is the public interface for - * creating new instances. - */ - static sptr make(); - - }; - - } // namespace satnogs -} // namespace gr - -#endif /* INCLUDED_SATNOGS_JSON_TO_ECSS_SRC_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 1a8d27d..64245da 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -35,7 +35,6 @@ list(APPEND satnogs_sources udp_msg_source_impl.cc 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 diff --git a/lib/json_to_ecss_src_impl.cc b/lib/json_to_ecss_src_impl.cc deleted file mode 100644 index 81f398a..0000000 --- a/lib/json_to_ecss_src_impl.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- 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 "json_to_ecss_src_impl.h" - -#include -#include - -#define BUFFER_SIZE 2048 - - -namespace gr { - namespace satnogs { - - json_to_ecss_src::sptr - json_to_ecss_src::make() - { - return gnuradio::get_initial_sptr - (new json_to_ecss_src_impl()); - } - - /* - * The private constructor - */ - json_to_ecss_src_impl::json_to_ecss_src_impl() - : gr::block("json_to_ecss_src", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - is_running(true), - d_in_port(pmt::mp("in")), - d_out_port(pmt::mp("out")) - { - message_port_register_out(d_out_port); - message_port_register_in(d_in_port); - - d_buf = (uint8_t*)malloc(BUFFER_SIZE * sizeof(uint8_t)); - - new boost::thread ( - boost::bind (&json_to_ecss_src_impl::json_accepter, this)); - } - - /* - * Our virtual destructor. - */ - json_to_ecss_src_impl::~json_to_ecss_src_impl() - { - is_running = false; - } - void - json_to_ecss_src_impl::json_accepter(){ - pmt::pmt_t message; - size_t length; - - while(is_running){ - message = delete_head_blocking(d_in_port); - length = blob_length(message); - d_buf = (uint8_t*)blob_data(message); - std::istringstream ss(std::string(d_buf, d_buf + length)); - ptree tree; - read_json(ss,tree); - BOOST_FOREACH(const ptree::value_type &v, tree) { - std::cout<<"First = "< Date: Tue, 11 Oct 2016 19:39:37 +0300 Subject: [PATCH 02/26] Rpi (#32) * Fix compilation on Raspbian * Add rtl-sdr dongle to the RX HW database --- CMakeLists.txt | 2 +- lib/coarse_doppler_correction_cc_impl.cc | 2 +- python/hw_settings.py | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3e50e1..16fe24e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ ######################################################################## # Project setup ######################################################################## -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(gr-satnogs CXX C) enable_testing() diff --git a/lib/coarse_doppler_correction_cc_impl.cc b/lib/coarse_doppler_correction_cc_impl.cc index 5442782..025fbc9 100644 --- a/lib/coarse_doppler_correction_cc_impl.cc +++ b/lib/coarse_doppler_correction_cc_impl.cc @@ -49,7 +49,7 @@ namespace gr gr::io_signature::make (1, 1, sizeof(gr_complex))), d_target_freq (target_freq), d_samp_rate (sampling_rate), - d_buf_items (std::min (8192UL, (size_t) (d_samp_rate / 4))), + d_buf_items (std::min ((size_t)8192UL, (size_t) (d_samp_rate / 4))), d_freq_diff (0), d_nco () { diff --git a/python/hw_settings.py b/python/hw_settings.py index 171bf87..730b463 100644 --- a/python/hw_settings.py +++ b/python/hw_settings.py @@ -44,4 +44,7 @@ hw_rx_settings = {'usrpb200' : {'rf_gain' : 20.0, 'if_gain' : 0.0, 'antenna' : '', 'dev_arg': 'airspy'}, 'hackrf' : {'rf_gain' : 20.0, 'if_gain' : 8.0, 'bb_gain' : 5.0, 'samp_rate' : 2e6, - 'antenna' : '', 'dev_arg': 'hackrf'} } + 'antenna' : '', 'dev_arg': 'hackrf'}, + 'rtlsdr' : {'rf_gain' : 32.0, 'if_gain' : 0.0, + 'bb_gain' : 0.0, 'samp_rate' : 1.024e6, + 'antenna' : '', 'dev_arg' : 'rtl'} } From 33a27566c89b058c88b32ba1ba3899473a20d833 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Wed, 12 Oct 2016 02:45:21 +0300 Subject: [PATCH 03/26] Improve build system and installation documentation (#33) The build systen now allows to enable/disable the blocks of the OOT module that are used for development and debugging purposes. --- CMakeLists.txt | 8 ++++++++ README.md | 27 +++++++++++++++++++++++++++ grc/CMakeLists.txt | 23 ++++++++++++++++++----- include/satnogs/CMakeLists.txt | 22 +++++++++++++++++----- lib/CMakeLists.txt | 14 +++++++++++--- lib/tcp_rigctl_msg_source_impl.cc | 2 +- swig/CMakeLists.txt | 11 ++++++++++- swig/satnogs_debug_swig.i | 23 +++++++++++++++++++++++ 8 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 swig/satnogs_debug_swig.i diff --git a/CMakeLists.txt b/CMakeLists.txt index 16fe24e..53ea76d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,14 @@ else(DOXYGEN_FOUND) option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) endif(DOXYGEN_FOUND) +######################################################################## +# Include or not into the module blocks for debugging +######################################################################## +if(NOT INCLUDE_DEBUG_BLOCKS) + set(INCLUDE_DEBUG_BLOCKS OFF CACHE BOOL + "Disable blocks that are used for debugging purposes") +endif() + ######################################################################## # Setup the include and linker paths ######################################################################## diff --git a/README.md b/README.md index bab7b67..438af03 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,33 @@ for decoding signals from various scientific and academic sattelites. If this is the first time you are building the gr-satnogs module run `sudo ldconfig` +#### Advanced +By default, the **SatNOGS** module will use the default installation prefix. +This highly depends on the Linux distribution. You can use the `CMAKE_INSTALL_PREFIX` +variable to alter the default installation path. +E.g: + +`cmake -DCMAKE_INSTALL_PREFIX=/usr ..` + +Also, by default the build system disables a set of blocks used for debugging +during the development. The enable/disable switch is controled through the +`INCLUDE_DEBUG_BLOCKS` boolean variable. If for example, you want to enable the +debugging blocks, the **CMake** command would be: + +`cmake -DINCLUDE_DEBUG_BLOCKS=OFF ..` + +Another common control option is the library sugffix of the Linux distribution. +There are distributions like Fedora, openSUSE, e.t.c that the their 64-bit version +use the `lib64` folder to store the 64-bit versions of their dynamic libraries. +On the other hand, distributions like Ubuntu do the exact opposite. They use +`lib` directory for the libraries of the native architecture and place the 32-bit versions +on the `lib32` directory. In any case the correct library directory suffix +can be specified with the `LIB_SUFFIX` variable. For example: + +`cmake -DLIB_SUFFIX=64 -DCMAKE_INSTALL_PREFIX=/usr -DINCLUDE_DEBUG_BLOCKS=OFF ..` + +will install the libraries at the `/usr/lib64` directory. + ## Website For more indormation about SatNOGS please visit our [site](https://satnogs.org/). diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index a625f6f..a9f297a 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -16,15 +16,20 @@ # 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 + +list(APPEND debug_blocks + satnogs_morse_debug_source.xml + satnogs_debug_msg_source.xml + satnogs_debug_msg_source_raw.xml +) + +list(APPEND enabled_blocks satnogs_cw_matched_filter_ff.xml satnogs_morse_decoder.xml - satnogs_morse_debug_source.xml satnogs_multi_format_msg_sink.xml satnogs_cw_to_symbol.xml satnogs_sine_matched_filter_ff.xml satnogs_udp_msg_source.xml - satnogs_debug_msg_source.xml satnogs_tcp_rigctl_msg_source.xml satnogs_frame_encoder.xml satnogs_doppler_correction_cc.xml @@ -34,8 +39,16 @@ install(FILES satnogs_udp_msg_sink.xml satnogs_upsat_transmitter.xml satnogs_coarse_doppler_correction_cc.xml - satnogs_debug_msg_source_raw.xml satnogs_ax25_encoder_mb.xml satnogs_ax25_decoder_bm.xml - satnogs_qb50_deframer.xml DESTINATION share/gnuradio/grc/blocks + satnogs_qb50_deframer.xml +) + +if(${INCLUDE_DEBUG_BLOCKS}) + list(APPEND enabled_blocks ${debug_blocks}) +endif() + +install(FILES + ${enabled_blocks} + DESTINATION share/gnuradio/grc/blocks ) diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index e874d38..5e29764 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -20,7 +20,13 @@ ######################################################################## # Install public header files ######################################################################## -install(FILES +list(APPEND DEBUG_HEADER_FILES + morse_debug_source.h + debug_msg_source_raw.h + debug_msg_source.h +) + +list(APPEND HEADER_FILES api.h ax25.h config.h @@ -29,13 +35,11 @@ install(FILES morse_tree.h morse.h morse_decoder.h - morse_debug_source.h multi_format_msg_sink.h cw_to_symbol.h sine_matched_filter_ff.h utils.h udp_msg_source.h - debug_msg_source.h tcp_rigctl_msg_source.h frame_encoder.h doppler_correction_cc.h @@ -46,8 +50,16 @@ install(FILES whitening.h udp_msg_sink.h coarse_doppler_correction_cc.h - debug_msg_source_raw.h ax25_encoder_mb.h ax25_decoder_bm.h - qb50_deframer.h DESTINATION include/satnogs + qb50_deframer.h ) + +if(${INCLUDE_DEBUG_BLOCKS}) + list(APPEND HEADER_FILES ${DEBUG_HEADER_FILES}) +endif() + +install(FILES + ${HEADER_FILES} + DESTINATION include/satnogs +) \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 64245da..f46e70e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -24,16 +24,21 @@ include(GrPlatform) #define LIB_SUFFIX include_directories(${Boost_INCLUDE_DIR}) link_directories(${Boost_LIBRARY_DIRS}) + +list(APPEND satnogs_debug_sources + morse_debug_source_impl.cc + debug_msg_source_impl.cc + debug_msg_source_raw_impl.cc +) + list(APPEND satnogs_sources cw_matched_filter_ff_impl.cc morse_tree.cc morse_decoder_impl.cc - morse_debug_source_impl.cc multi_format_msg_sink_impl.cc cw_to_symbol_impl.cc sine_matched_filter_ff_impl.cc udp_msg_source_impl.cc - debug_msg_source_impl.cc tcp_rigctl_msg_source_impl.cc doppler_correction_cc_impl.cc frame_encoder_impl.cc @@ -44,11 +49,14 @@ list(APPEND satnogs_sources whitening.cc udp_msg_sink_impl.cc coarse_doppler_correction_cc_impl.cc - debug_msg_source_raw_impl.cc ax25_encoder_mb_impl.cc ax25_decoder_bm_impl.cc qb50_deframer_impl.cc ) +if(${INCLUDE_DEBUG_BLOCKS}) + list(APPEND satnogs_sources ${satnogs_debug_sources}) +endif() + set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE) if(NOT satnogs_sources) MESSAGE(STATUS "No C++ sources... skipping lib/") diff --git a/lib/tcp_rigctl_msg_source_impl.cc b/lib/tcp_rigctl_msg_source_impl.cc index 51c08a9..8a10b35 100644 --- a/lib/tcp_rigctl_msg_source_impl.cc +++ b/lib/tcp_rigctl_msg_source_impl.cc @@ -161,7 +161,7 @@ namespace gr * NOTE: Comparison for equality in floats is a bit tricky. * But here the get_freq_from_buf() will assign a 0.0 explicitly * if something goes wrong. For this reason it is safe to compare - * the in-equality agains 0.0. + * the in-equality against 0.0. */ if (freq != 0.0) { reported_freq = freq; diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt index f4a3cd8..83ab67d 100644 --- a/swig/CMakeLists.txt +++ b/swig/CMakeLists.txt @@ -57,9 +57,18 @@ GR_SWIG_INSTALL(TARGETS satnogs_swig DESTINATION ${GR_PYTHON_DIR}/satnogs) ######################################################################## # Install swig .i files for development ######################################################################## +list(APPEND swig_files + satnogs_swig.i + ${CMAKE_CURRENT_BINARY_DIR}/satnogs_swig_doc.i +) + +if(${INCLUDE_DEBUG_BLOCKS}) + list(APPEND swig_files "satnogs_debug_swig.i") +endif() + install( FILES - satnogs_swig.i + ${swig_files} ${CMAKE_CURRENT_BINARY_DIR}/satnogs_swig_doc.i DESTINATION ${GR_INCLUDE_DIR}/satnogs/swig ) diff --git a/swig/satnogs_debug_swig.i b/swig/satnogs_debug_swig.i new file mode 100644 index 0000000..bfd32f8 --- /dev/null +++ b/swig/satnogs_debug_swig.i @@ -0,0 +1,23 @@ +/* -*- c++ -*- */ + +%include +%include "gnuradio.i" // the common stuff + +//load generated python docstrings +%include "satnogs_swig_doc.i" + +%{ +#include "satnogs/morse_debug_source.h" +#include "satnogs/debug_msg_source.h" +#include "satnogs/debug_msg_source_raw.h" +%} + +%include "satnogs/morse_debug_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, morse_debug_source); + +%include "satnogs/debug_msg_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source); + +%include "satnogs/debug_msg_source_raw.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source_raw); + From ce8d54eb40cda500f9b5a75f503e1a1235d862af Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Wed, 12 Oct 2016 21:22:48 +0300 Subject: [PATCH 04/26] Improve the generic FM demodulator The FM demodulator now supports a variaty of hardware setups and saves the WAV file for further processing. A set of command line arguments can control most of the flowgraph internals, such as the wav file name and storage path e.t.c. TODO: Check the settings for all the available hardware --- apps/CMakeLists.txt | 1 + apps/flowgraphs/fm_demod.grc | 552 +++++++++++----------- apps/flowgraphs/satnogs_fm_demod.py | 258 ++++++++++ apps/flowgraphs/upsat_transceiver_cli.grc | 16 +- apps/flowgraphs/upsat_transceiver_cli.py | 31 +- python/CMakeLists.txt | 1 + python/__init__.py | 1 + python/dsp_settings.py | 31 ++ 8 files changed, 597 insertions(+), 294 deletions(-) create mode 100755 apps/flowgraphs/satnogs_fm_demod.py create mode 100644 python/dsp_settings.py diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 26a9f2c..da2c642 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -22,5 +22,6 @@ include(GrPython) GR_PYTHON_INSTALL( PROGRAMS flowgraphs/upsat_transceiver_cli.py + flowgraphs/satnogs_fm_demod.py DESTINATION bin ) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index ed84873..a5a4d96 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -1,12 +1,12 @@ - + Thu May 5 00:22:45 2016 options author - + Manolis Surligas (surligas@gmail.com) window_size @@ -22,7 +22,7 @@ description - + A generic FM demodulation block _enabled @@ -46,7 +46,7 @@ id - fm_demod + satnogs_fm_demod max_nouts @@ -78,7 +78,7 @@ title - + FM Generic Demodulation @@ -93,7 +93,7 @@ _coordinate - (480, 21) + (568, 508) _rotation @@ -109,14 +109,12 @@ - variable_qtgui_range + variable comment - - - - value - 0.9 + Decimation factor +for the RX after the +SDR received samples _enabled @@ -124,11 +122,7 @@ _coordinate - (1048, 249) - - - gui_hint - + (336, 612) _rotation @@ -139,36 +133,8 @@ audio_gain - label - Audio Gain - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.01 - - - stop - 8 - - - rangeType - float - - - widget - counter_slider + value + satnogs.fm_demod_settings[rx_sdr_device]['audio_gain'] @@ -183,7 +149,7 @@ _coordinate - (480, 93) + (568, 580) _rotation @@ -212,7 +178,7 @@ SDR received samples _coordinate - (232, 21) + (192, 612) _rotation @@ -224,161 +190,7 @@ SDR received samples value - 10 - - - - variable_qtgui_range - - comment - - - - value - 100e6 - - - _enabled - True - - - _coordinate - (1048, 24) - - - gui_hint - - - - _rotation - 0 - - - id - freq - - - label - RX Frequency - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 92e6 - - - step - 100e3 - - - stop - 105e6 - - - rangeType - float - - - widget - counter_slider - - - - variable_qtgui_range - - comment - - - - value - 10 - - - _enabled - True - - - _coordinate - (1048, 137) - - - gui_hint - - - - _rotation - 0 - - - id - gain - - - label - RX RF Gain - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider - - - - variable - - comment - To avoid the SDR carrier at the DC -we shift the LO a little further - - - _enabled - True - - - _coordinate - (832, 18) - - - _rotation - 0 - - - id - lo_offset - - - value - 100e3 + satnogs.fm_demod_settings[rx_sdr_device]['decimation_rx'] @@ -393,7 +205,7 @@ we shift the LO a little further _coordinate - (360, 21) + (432, 476) _rotation @@ -412,7 +224,8 @@ we shift the LO a little further variable comment - + SDR device +TX sampling rate _enabled @@ -420,7 +233,7 @@ we shift the LO a little further _coordinate - (8, 160) + (192, 484) _rotation @@ -432,7 +245,7 @@ we shift the LO a little further value - 10e6 + satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] @@ -455,7 +268,7 @@ we shift the LO a little further _coordinate - (664, 18) + (560, 648) _rotation @@ -502,7 +315,7 @@ we shift the LO a little further _enabled - 1 + 0 freq @@ -510,7 +323,7 @@ we shift the LO a little further _coordinate - (296, 192) + (312, 24) _rotation @@ -569,7 +382,7 @@ we shift the LO a little further _coordinate - (712, 501) + (736, 292) _rotation @@ -592,53 +405,6 @@ we shift the LO a little further quadrature_rate - - audio_sink - - alias - - - - comment - - - - affinity - - - - device_name - - - - _enabled - 1 - - - _coordinate - (776, 668) - - - _rotation - 180 - - - id - audio_sink_0 - - - num_inputs - 1 - - - ok_to_block - True - - - samp_rate - audio_samp_rate - - blocks_multiply_const_vxx @@ -663,7 +429,7 @@ we shift the LO a little further _coordinate - (968, 668) + (976, 444) _rotation @@ -706,11 +472,11 @@ we shift the LO a little further _enabled - 1 + 0 _coordinate - (568, 264) + (568, 64) _rotation @@ -741,6 +507,96 @@ we shift the LO a little further 1 + + blocks_wavfile_sink + + bits_per_sample + 16 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + file_path + + + _coordinate + (800, 428) + + + _rotation + 180 + + + id + blocks_wavfile_sink_0 + + + nchan + 1 + + + samp_rate + audio_samp_rate + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 620) + + + _rotation + 0 + + + id + file_path + + + label + + + + short_id + + + + type + string + + + value + test.wav + + freq_xlating_fir_filter_xxx @@ -769,7 +625,7 @@ we shift the LO a little further _coordinate - (496, 487) + (520, 280) _rotation @@ -800,6 +656,50 @@ we shift the LO a little further ccc + + parameter + + alias + + + + comment + To avoid the SDR carrier at the DC +we shift the LO a little further + + + _enabled + True + + + _coordinate + (328, 476) + + + _rotation + 0 + + + id + lo_offset + + + label + + + + short_id + + + + type + eng_float + + + value + 100e3 + + osmosdr_source @@ -808,11 +708,11 @@ we shift the LO a little further ant0 - + satnogs.hw_rx_settings[rx_sdr_device]['antenna'] bb_gain0 - 20 + satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'] bw0 @@ -828,7 +728,7 @@ we shift the LO a little further freq0 - freq - lo_offset + rx_freq - lo_offset gain_mode0 @@ -836,7 +736,7 @@ we shift the LO a little further if_gain0 - 20 + satnogs.hw_rx_settings[rx_sdr_device]['if_gain'] iq_balance_mode0 @@ -844,7 +744,7 @@ we shift the LO a little further gain0 - gain + satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'] ant10 @@ -2096,7 +1996,7 @@ we shift the LO a little further args - + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] _enabled @@ -2104,7 +2004,7 @@ we shift the LO a little further _coordinate - (104, 229) + (24, 256) _rotation @@ -2227,7 +2127,7 @@ we shift the LO a little further _coordinate - (904, 487) + (944, 288) _rotation @@ -2280,6 +2180,10 @@ we shift the LO a little further average 1.0 + + axislabels + True + bw samp_rate_rx @@ -2306,7 +2210,7 @@ we shift the LO a little further _enabled - 1 + 0 fftsize @@ -2314,7 +2218,7 @@ we shift the LO a little further _coordinate - (896, 262) + (792, 28) gui_hint @@ -2548,6 +2452,10 @@ we shift the LO a little further wintype firdes.WIN_BLACKMAN_hARRIS + + label + Relative Gain + ymax 10 @@ -2556,6 +2464,96 @@ we shift the LO a little further ymin -140 + + units + dB + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 724) + + + _rotation + 0 + + + id + rx_freq + + + label + + + + short_id + + + + type + eng_float + + + value + 100e6 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 484) + + + _rotation + 0 + + + id + rx_sdr_device + + + label + + + + short_id + + + + type + string + + + value + usrpb200 + satnogs_doppler_correction_cc @@ -2581,7 +2579,7 @@ we shift the LO a little further _coordinate - (280, 464) + (304, 256) _rotation @@ -2605,7 +2603,7 @@ we shift the LO a little further target_freq - freq + rx_freq @@ -2628,7 +2626,7 @@ we shift the LO a little further _coordinate - (24, 446) + (24, 164) _rotation @@ -2673,7 +2671,7 @@ we shift the LO a little further blocks_multiply_const_vxx_0 - audio_sink_0 + blocks_wavfile_sink_0 0 0 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py new file mode 100755 index 0000000..3eccf05 --- /dev/null +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: FM Generic Demodulation +# Author: Manolis Surligas (surligas@gmail.com) +# Description: A generic FM demodulation block +# Generated: Wed Oct 12 21:16:27 2016 +################################################## + +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print "Warning: failed to XInitThreads()" + +from PyQt4 import Qt +from gnuradio import analog +from gnuradio import blocks +from gnuradio import eng_notation +from gnuradio import filter +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.filter import firdes +from gnuradio.filter import pfb +from optparse import OptionParser +import osmosdr +import satnogs +import sys +import time + + +class satnogs_fm_demod(gr.top_block, Qt.QWidget): + + def __init__(self, file_path="test.wav", lo_offset=100e3, rx_freq=100e6, rx_sdr_device="usrpb200"): + gr.top_block.__init__(self, "FM Generic Demodulation") + Qt.QWidget.__init__(self) + self.setWindowTitle("FM Generic Demodulation") + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + + self.settings = Qt.QSettings("GNU Radio", "satnogs_fm_demod") + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + + ################################################## + # Parameters + ################################################## + self.file_path = file_path + self.lo_offset = lo_offset + self.rx_freq = rx_freq + self.rx_sdr_device = rx_sdr_device + + ################################################## + # Variables + ################################################## + self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] + self.decimation_rx = decimation_rx = satnogs.fm_demod_settings[rx_sdr_device]['decimation_rx'] + + self.taps = taps = firdes.low_pass(12.0, samp_rate_rx, 100e3, 60000, firdes.WIN_HAMMING, 6.76) + + self.quadrature_rate = quadrature_rate = samp_rate_rx / decimation_rx + self.audio_samp_rate = audio_samp_rate = 44100 + self.audio_gain = audio_gain = satnogs.fm_demod_settings[rx_sdr_device]['audio_gain'] + self.audio_decimation = audio_decimation = 2 + + ################################################## + # Blocks + ################################################## + self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", 4532, 1500) + self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, 1000) + self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( + audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation), + taps=(firdes.low_pass_2(32, 32, 0.8, 0.1, 100)), + flt_size=32) + self.pfb_arb_resampler_xxx_0.declare_sample_delay(0) + + self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) + self.osmosdr_source_0.set_sample_rate(samp_rate_rx) + self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) + self.osmosdr_source_0.set_freq_corr(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_iq_balance_mode(0, 0) + self.osmosdr_source_0.set_gain_mode(False, 0) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0) + self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) + + self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(decimation_rx, (taps), lo_offset, samp_rate_rx) + self.blocks_wavfile_sink_0 = blocks.wavfile_sink(file_path, 1, audio_samp_rate, 16) + self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((audio_gain, )) + self.analog_wfm_rcv_0 = analog.wfm_rcv( + quad_rate=quadrature_rate, + audio_decimation=audio_decimation, + ) + + ################################################## + # Connections + ################################################## + self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_doppler_correction_cc_0, 'freq')) + self.connect((self.analog_wfm_rcv_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) + self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_wavfile_sink_0, 0)) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.analog_wfm_rcv_0, 0)) + self.connect((self.osmosdr_source_0, 0), (self.satnogs_doppler_correction_cc_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_multiply_const_vxx_0, 0)) + self.connect((self.satnogs_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "satnogs_fm_demod") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + + def get_file_path(self): + return self.file_path + + def set_file_path(self, file_path): + self.file_path = file_path + self.blocks_wavfile_sink_0.open(self.file_path) + + def get_lo_offset(self): + return self.lo_offset + + def set_lo_offset(self, lo_offset): + self.lo_offset = lo_offset + self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) + self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + + def get_rx_freq(self): + return self.rx_freq + + def set_rx_freq(self, rx_freq): + self.rx_freq = rx_freq + self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) + + def get_rx_sdr_device(self): + return self.rx_sdr_device + + def set_rx_sdr_device(self, rx_sdr_device): + self.rx_sdr_device = rx_sdr_device + self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) + self.set_decimation_rx(satnogs.fm_demod_settings[self.rx_sdr_device]['decimation_rx']) + self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain']) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0) + + def get_samp_rate_rx(self): + return self.samp_rate_rx + + def set_samp_rate_rx(self, samp_rate_rx): + self.samp_rate_rx = samp_rate_rx + self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx) + self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0) + + def get_decimation_rx(self): + return self.decimation_rx + + def set_decimation_rx(self, decimation_rx): + self.decimation_rx = decimation_rx + self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.freq_xlating_fir_filter_xxx_0.set_taps((self.taps)) + + def get_quadrature_rate(self): + return self.quadrature_rate + + def set_quadrature_rate(self, quadrature_rate): + self.quadrature_rate = quadrature_rate + self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) + + def get_audio_samp_rate(self): + return self.audio_samp_rate + + def set_audio_samp_rate(self, audio_samp_rate): + self.audio_samp_rate = audio_samp_rate + self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) + + def get_audio_gain(self): + return self.audio_gain + + def set_audio_gain(self, audio_gain): + self.audio_gain = audio_gain + self.blocks_multiply_const_vxx_0.set_k((self.audio_gain, )) + + def get_audio_decimation(self): + return self.audio_decimation + + def set_audio_decimation(self, audio_decimation): + self.audio_decimation = audio_decimation + self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) + + +def argument_parser(): + description = 'A generic FM demodulation block' + parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) + parser.add_option( + "", "--file-path", dest="file_path", type="string", default="test.wav", + help="Set file_path [default=%default]") + parser.add_option( + "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), + help="Set lo_offset [default=%default]") + parser.add_option( + "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6), + help="Set rx_freq [default=%default]") + parser.add_option( + "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default="usrpb200", + help="Set rx_sdr_device [default=%default]") + return parser + + +def main(top_block_cls=satnogs_fm_demod, options=None): + if options is None: + options, _ = argument_parser().parse_args() + + from distutils.version import StrictVersion + if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): + style = gr.prefs().get_string('qtgui', 'style', 'raster') + Qt.QApplication.setGraphicsSystem(style) + qapp = Qt.QApplication(sys.argv) + + tb = top_block_cls(file_path=options.file_path, lo_offset=options.lo_offset, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device) + tb.start() + tb.show() + + def quitting(): + tb.stop() + tb.wait() + qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting) + qapp.exec_() + + +if __name__ == '__main__': + main() diff --git a/apps/flowgraphs/upsat_transceiver_cli.grc b/apps/flowgraphs/upsat_transceiver_cli.grc index fe92a65..09d37b8 100644 --- a/apps/flowgraphs/upsat_transceiver_cli.grc +++ b/apps/flowgraphs/upsat_transceiver_cli.grc @@ -1,5 +1,5 @@ - + Fri Jul 1 17:53:00 2016 @@ -78,7 +78,7 @@ title - + UPSat Tranceiver @@ -3676,6 +3676,10 @@ we shift the LO a little further average 1.0 + + axislabels + True + bw samp_rate_rx/decimation_rx @@ -3944,6 +3948,10 @@ we shift the LO a little further wintype firdes.WIN_BLACKMAN_hARRIS + + label + Relative Gain + ymax 0 @@ -3952,6 +3960,10 @@ we shift the LO a little further ymin -140 + + units + dB + parameter diff --git a/apps/flowgraphs/upsat_transceiver_cli.py b/apps/flowgraphs/upsat_transceiver_cli.py index e566cbe..de55623 100755 --- a/apps/flowgraphs/upsat_transceiver_cli.py +++ b/apps/flowgraphs/upsat_transceiver_cli.py @@ -2,10 +2,10 @@ # -*- coding: utf-8 -*- ################################################## # GNU Radio Python Flow Graph -# Title: Upsat Transceiver Cli +# Title: UPSat Tranceiver # Author: Manolis Surligas (surligas@gmail.com) # Description: SATNOGS transceiver for UPSAT satellite -# Generated: Sun Aug 14 22:13:27 2016 +# Generated: Wed Oct 12 20:16:02 2016 ################################################## from gnuradio import analog @@ -28,7 +28,7 @@ import time class upsat_transceiver_cli(gr.top_block): def __init__(self, bind_addr="0.0.0.0", dest_addr="127.0.0.1", lo_offset=100e3, recv_port=16886, rx_sdr_device="usrpb200", send_port=5022, tx_sdr_device="usrpb200", wod_port=5023): - gr.top_block.__init__(self, "Upsat Transceiver Cli") + gr.top_block.__init__(self, "UPSat Tranceiver") ################################################## # Parameters @@ -150,10 +150,10 @@ class upsat_transceiver_cli(gr.top_block): def set_lo_offset(self, lo_offset): self.lo_offset = lo_offset - self.analog_sig_source_x_0.set_frequency(self.lo_offset ) - self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) - self.osmosdr_sink_0.set_center_freq(self.tx_frequency - self.lo_offset, 0) self.osmosdr_source_0.set_center_freq(self.rx_frequency - self.lo_offset, 0) + self.osmosdr_sink_0.set_center_freq(self.tx_frequency - self.lo_offset, 0) + self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + self.analog_sig_source_x_0.set_frequency(self.lo_offset ) def get_recv_port(self): return self.recv_port @@ -166,8 +166,8 @@ class upsat_transceiver_cli(gr.top_block): def set_rx_sdr_device(self, rx_sdr_device): self.rx_sdr_device = rx_sdr_device - self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) self.set_samp_rate_tx(satnogs.hw_tx_settings[self.rx_sdr_device]['samp_rate']) + self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0) self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0) self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0) @@ -200,10 +200,10 @@ class upsat_transceiver_cli(gr.top_block): def set_samples_per_symbol_tx(self, samples_per_symbol_tx): self.samples_per_symbol_tx = samples_per_symbol_tx - self.set_gaussian_taps(filter.firdes.gaussian(1.0, self.samples_per_symbol_tx, 1.0, 4*self.samples_per_symbol_tx)) self.set_sq_wave((1.0, ) * self.samples_per_symbol_tx) - self.analog_frequency_modulator_fc_0.set_sensitivity((math.pi*self.modulation_index_uplink) / self.samples_per_symbol_tx) self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) + self.set_gaussian_taps(filter.firdes.gaussian(1.0, self.samples_per_symbol_tx, 1.0, 4*self.samples_per_symbol_tx)) + self.analog_frequency_modulator_fc_0.set_sensitivity((math.pi*self.modulation_index_uplink) / self.samples_per_symbol_tx) def get_sq_wave(self): return self.sq_wave @@ -233,8 +233,8 @@ class upsat_transceiver_cli(gr.top_block): def set_deviation(self, deviation): self.deviation = deviation - self.set_modulation_index_downlink(self.deviation / (self.baud_rate_downlink / 2.0)) self.set_modulation_index_uplink(self.deviation / (self.baud_rate_uplink / 2.0)) + self.set_modulation_index_downlink(self.deviation / (self.baud_rate_downlink / 2.0)) def get_decimation_rx(self): return self.decimation_rx @@ -257,8 +257,8 @@ class upsat_transceiver_cli(gr.top_block): def set_baud_rate_downlink(self, baud_rate_downlink): self.baud_rate_downlink = baud_rate_downlink self.set_modulation_index_downlink(self.deviation / (self.baud_rate_downlink / 2.0)) - self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) self.digital_clock_recovery_mm_xx_0.set_omega(self.first_stage_samp_rate_rx/self.baud_rate_downlink) + self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) def get_tx_frequency(self): return self.tx_frequency @@ -279,10 +279,10 @@ class upsat_transceiver_cli(gr.top_block): def set_samp_rate_tx(self, samp_rate_tx): self.samp_rate_tx = samp_rate_tx - self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate_tx) + self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) self.osmosdr_sink_0.set_sample_rate(self.samp_rate_tx) self.osmosdr_sink_0.set_bandwidth(self.samp_rate_tx, 0) - self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) + self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate_tx) def get_rx_frequency(self): return self.rx_frequency @@ -317,12 +317,13 @@ class upsat_transceiver_cli(gr.top_block): def set_first_stage_samp_rate_rx(self, first_stage_samp_rate_rx): self.first_stage_samp_rate_rx = first_stage_samp_rate_rx - self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) self.digital_clock_recovery_mm_xx_0.set_omega(self.first_stage_samp_rate_rx/self.baud_rate_downlink) + self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) def argument_parser(): - parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + description = 'SATNOGS transceiver for UPSAT satellite' + parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) parser.add_option( "", "--bind-addr", dest="bind_addr", type="string", default="0.0.0.0", help="Set bind_addr [default=%default]") diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 62ef720..92177f4 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -31,6 +31,7 @@ endif() GR_PYTHON_INSTALL( FILES __init__.py + dsp_settings.py hw_settings.py satnogs_upsat_transmitter.py DESTINATION ${GR_PYTHON_DIR}/satnogs diff --git a/python/__init__.py b/python/__init__.py index 6950aa0..80199ba 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -27,6 +27,7 @@ description here (python/__init__.py). try: # this might fail if the module is python-only from satnogs_swig import * + from dsp_settings import * from hw_settings import * from satnogs_upsat_transmitter import * except ImportError: diff --git a/python/dsp_settings.py b/python/dsp_settings.py new file mode 100644 index 0000000..52911c0 --- /dev/null +++ b/python/dsp_settings.py @@ -0,0 +1,31 @@ +#! /usr/bin/python +# +# 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 +# + +#=============================================================================== +# This file provides a variaty of settings for the flowgraphs +# based on the hardware SDR device that they are using +#=============================================================================== + +fm_demod_settings = {'usrpb200' : {'decimation_rx' : 5, 'audio_gain' : 0.9}, + 'usrp2' : {'decimation_rx' : 5, 'audio_gain' : 0.9}, + 'airspy' : {'decimation_rx' : 10, 'audio_gain' : 0.9}, + 'hackrf' : {'decimation_rx' : 5, 'audio_gain' : 0.9}, + 'rtlsdr' : {'decimation_rx' : 5, 'audio_gain' : 0.9} + } \ No newline at end of file From 3577b3ae93d37e193e8257df34dcfb0fedefd78a Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Mon, 17 Oct 2016 19:34:45 +0300 Subject: [PATCH 05/26] Add more control parameters at the flowgraphs * Add generic IQ samples recorder. This can be a useful flowgraph to perform an observation and use the stored file for offline analysis. --- apps/CMakeLists.txt | 1 + apps/flowgraphs/fm_demod.grc | 96 +- apps/flowgraphs/generic_iq_receiver.grc | 2631 +++++++++++++++++ apps/flowgraphs/satnogs_fm_demod.py | 81 +- .../flowgraphs/satnogs_generic_iq_receiver.py | 210 ++ 5 files changed, 2959 insertions(+), 60 deletions(-) create mode 100644 apps/flowgraphs/generic_iq_receiver.grc create mode 100755 apps/flowgraphs/satnogs_generic_iq_receiver.py diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index da2c642..318d7ea 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -23,5 +23,6 @@ GR_PYTHON_INSTALL( PROGRAMS flowgraphs/upsat_transceiver_cli.py flowgraphs/satnogs_fm_demod.py + flowgraphs/satnogs_generic_iq_receiver.py DESTINATION bin ) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index a5a4d96..64f1ccd 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -38,7 +38,7 @@ generate_options - qt_gui + no_gui hier_block_src_path @@ -66,7 +66,7 @@ run_options - prompt + run run @@ -554,6 +554,49 @@ TX sampling rate audio_samp_rate + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 860) + + + _rotation + 0 + + + id + doppler_correction_per_sec + + + label + + + + short_id + + + + type + intx + + + value + 1000 + + parameter @@ -2485,7 +2528,50 @@ we shift the LO a little further _coordinate - (64, 724) + (64, 780) + + + _rotation + 0 + + + id + rigctl_port + + + label + + + + short_id + + + + type + intx + + + value + 4532 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 700) _rotation @@ -2571,7 +2657,7 @@ we shift the LO a little further corrections_per_sec - 1000 + doppler_correction_per_sec _enabled @@ -2642,7 +2728,7 @@ we shift the LO a little further port - 4532 + rigctl_port mtu diff --git a/apps/flowgraphs/generic_iq_receiver.grc b/apps/flowgraphs/generic_iq_receiver.grc new file mode 100644 index 0000000..ed25c2a --- /dev/null +++ b/apps/flowgraphs/generic_iq_receiver.grc @@ -0,0 +1,2631 @@ + + + + Thu May 5 00:22:45 2016 + + options + + author + Manolis Surligas (surligas@gmail.com) + + + window_size + + + + category + Custom + + + comment + + + + description + A generic FM demodulation block + + + _enabled + True + + + _coordinate + (8, 8) + + + _rotation + 0 + + + generate_options + no_gui + + + hier_block_src_path + .: + + + id + satnogs_generic_iq_receiver + + + max_nouts + 0 + + + qt_qss_theme + + + + realtime_scheduling + + + + run_command + {python} -u {filename} + + + run_options + run + + + run + True + + + thread_safe_setters + + + + title + Generic IQ samples receiver + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (568, 508) + + + _rotation + 0 + + + id + audio_decimation + + + value + 2 + + + + variable + + comment + Decimation factor +for the RX after the +SDR received samples + + + _enabled + True + + + _coordinate + (336, 612) + + + _rotation + 0 + + + id + audio_gain + + + value + satnogs.fm_demod_settings[rx_sdr_device]['audio_gain'] + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (568, 580) + + + _rotation + 0 + + + id + audio_samp_rate + + + value + 44100 + + + + variable + + comment + Decimation factor +for the RX after the +SDR received samples + + + _enabled + True + + + _coordinate + (192, 612) + + + _rotation + 0 + + + id + decimation_rx + + + value + satnogs.fm_demod_settings[rx_sdr_device]['decimation_rx'] + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (432, 476) + + + _rotation + 0 + + + id + quadrature_rate + + + value + samp_rate_rx / decimation_rx + + + + variable + + comment + SDR device +TX sampling rate + + + _enabled + True + + + _coordinate + (192, 484) + + + _rotation + 0 + + + id + samp_rate_rx + + + value + satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] + + + + variable_low_pass_filter_taps + + beta + 6.76 + + + comment + + + + cutoff_freq + 100e3 + + + _enabled + 1 + + + _coordinate + (560, 648) + + + _rotation + 0 + + + gain + 12.0 + + + id + taps + + + samp_rate + samp_rate_rx + + + width + 60000 + + + win + firdes.WIN_HAMMING + + + + analog_sig_source_x + + amp + 1 + + + alias + + + + comment + + + + affinity + + + + _enabled + 0 + + + freq + -lo_offset + + + _coordinate + (312, 24) + + + _rotation + 0 + + + id + analog_sig_source_x_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + offset + 0 + + + type + complex + + + samp_rate + samp_rate_rx + + + waveform + analog.GR_COS_WAVE + + + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + file_path + + + _coordinate + (784, 284) + + + _rotation + 0 + + + id + blocks_file_sink_0 + + + type + complex + + + unbuffered + True + + + vlen + 1 + + + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + 0 + + + _coordinate + (568, 64) + + + _rotation + 0 + + + id + blocks_multiply_xx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 860) + + + _rotation + 0 + + + id + doppler_correction_per_sec + + + label + + + + short_id + + + + type + intx + + + value + 1000 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 620) + + + _rotation + 0 + + + id + file_path + + + label + + + + short_id + + + + type + string + + + value + test.wav + + + + freq_xlating_fir_filter_xxx + + alias + + + + center_freq + lo_offset + + + comment + + + + affinity + + + + decim + decimation_rx + + + _enabled + 1 + + + _coordinate + (520, 280) + + + _rotation + 0 + + + id + freq_xlating_fir_filter_xxx_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + samp_rate_rx + + + taps + taps + + + type + ccc + + + + parameter + + alias + + + + comment + To avoid the SDR carrier at the DC +we shift the LO a little further + + + _enabled + True + + + _coordinate + (328, 476) + + + _rotation + 0 + + + id + lo_offset + + + label + + + + short_id + + + + type + eng_float + + + value + 100e3 + + + + osmosdr_source + + alias + + + + ant0 + satnogs.hw_rx_settings[rx_sdr_device]['antenna'] + + + bb_gain0 + satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'] + + + bw0 + samp_rate_rx + + + dc_offset_mode0 + 0 + + + corr0 + 0 + + + freq0 + rx_freq - lo_offset + + + gain_mode0 + False + + + if_gain0 + satnogs.hw_rx_settings[rx_sdr_device]['if_gain'] + + + iq_balance_mode0 + 0 + + + gain0 + satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'] + + + ant10 + + + + bb_gain10 + 20 + + + bw10 + 0 + + + dc_offset_mode10 + 0 + + + corr10 + 0 + + + freq10 + 100e6 + + + gain_mode10 + False + + + if_gain10 + 20 + + + iq_balance_mode10 + 0 + + + gain10 + 10 + + + ant11 + + + + bb_gain11 + 20 + + + bw11 + 0 + + + dc_offset_mode11 + 0 + + + corr11 + 0 + + + freq11 + 100e6 + + + gain_mode11 + False + + + if_gain11 + 20 + + + iq_balance_mode11 + 0 + + + gain11 + 10 + + + ant12 + + + + bb_gain12 + 20 + + + bw12 + 0 + + + dc_offset_mode12 + 0 + + + corr12 + 0 + + + freq12 + 100e6 + + + gain_mode12 + False + + + if_gain12 + 20 + + + iq_balance_mode12 + 0 + + + gain12 + 10 + + + ant13 + + + + bb_gain13 + 20 + + + bw13 + 0 + + + dc_offset_mode13 + 0 + + + corr13 + 0 + + + freq13 + 100e6 + + + gain_mode13 + False + + + if_gain13 + 20 + + + iq_balance_mode13 + 0 + + + gain13 + 10 + + + ant14 + + + + bb_gain14 + 20 + + + bw14 + 0 + + + dc_offset_mode14 + 0 + + + corr14 + 0 + + + freq14 + 100e6 + + + gain_mode14 + False + + + if_gain14 + 20 + + + iq_balance_mode14 + 0 + + + gain14 + 10 + + + ant15 + + + + bb_gain15 + 20 + + + bw15 + 0 + + + dc_offset_mode15 + 0 + + + corr15 + 0 + + + freq15 + 100e6 + + + gain_mode15 + False + + + if_gain15 + 20 + + + iq_balance_mode15 + 0 + + + gain15 + 10 + + + ant16 + + + + bb_gain16 + 20 + + + bw16 + 0 + + + dc_offset_mode16 + 0 + + + corr16 + 0 + + + freq16 + 100e6 + + + gain_mode16 + False + + + if_gain16 + 20 + + + iq_balance_mode16 + 0 + + + gain16 + 10 + + + ant17 + + + + bb_gain17 + 20 + + + bw17 + 0 + + + dc_offset_mode17 + 0 + + + corr17 + 0 + + + freq17 + 100e6 + + + gain_mode17 + False + + + if_gain17 + 20 + + + iq_balance_mode17 + 0 + + + gain17 + 10 + + + ant18 + + + + bb_gain18 + 20 + + + bw18 + 0 + + + dc_offset_mode18 + 0 + + + corr18 + 0 + + + freq18 + 100e6 + + + gain_mode18 + False + + + if_gain18 + 20 + + + iq_balance_mode18 + 0 + + + gain18 + 10 + + + ant19 + + + + bb_gain19 + 20 + + + bw19 + 0 + + + dc_offset_mode19 + 0 + + + corr19 + 0 + + + freq19 + 100e6 + + + gain_mode19 + False + + + if_gain19 + 20 + + + iq_balance_mode19 + 0 + + + gain19 + 10 + + + ant1 + + + + bb_gain1 + 20 + + + bw1 + 0 + + + dc_offset_mode1 + 0 + + + corr1 + 0 + + + freq1 + 100e6 + + + gain_mode1 + False + + + if_gain1 + 20 + + + iq_balance_mode1 + 0 + + + gain1 + 10 + + + ant20 + + + + bb_gain20 + 20 + + + bw20 + 0 + + + dc_offset_mode20 + 0 + + + corr20 + 0 + + + freq20 + 100e6 + + + gain_mode20 + False + + + if_gain20 + 20 + + + iq_balance_mode20 + 0 + + + gain20 + 10 + + + ant21 + + + + bb_gain21 + 20 + + + bw21 + 0 + + + dc_offset_mode21 + 0 + + + corr21 + 0 + + + freq21 + 100e6 + + + gain_mode21 + False + + + if_gain21 + 20 + + + iq_balance_mode21 + 0 + + + gain21 + 10 + + + ant22 + + + + bb_gain22 + 20 + + + bw22 + 0 + + + dc_offset_mode22 + 0 + + + corr22 + 0 + + + freq22 + 100e6 + + + gain_mode22 + False + + + if_gain22 + 20 + + + iq_balance_mode22 + 0 + + + gain22 + 10 + + + ant23 + + + + bb_gain23 + 20 + + + bw23 + 0 + + + dc_offset_mode23 + 0 + + + corr23 + 0 + + + freq23 + 100e6 + + + gain_mode23 + False + + + if_gain23 + 20 + + + iq_balance_mode23 + 0 + + + gain23 + 10 + + + ant24 + + + + bb_gain24 + 20 + + + bw24 + 0 + + + dc_offset_mode24 + 0 + + + corr24 + 0 + + + freq24 + 100e6 + + + gain_mode24 + False + + + if_gain24 + 20 + + + iq_balance_mode24 + 0 + + + gain24 + 10 + + + ant25 + + + + bb_gain25 + 20 + + + bw25 + 0 + + + dc_offset_mode25 + 0 + + + corr25 + 0 + + + freq25 + 100e6 + + + gain_mode25 + False + + + if_gain25 + 20 + + + iq_balance_mode25 + 0 + + + gain25 + 10 + + + ant26 + + + + bb_gain26 + 20 + + + bw26 + 0 + + + dc_offset_mode26 + 0 + + + corr26 + 0 + + + freq26 + 100e6 + + + gain_mode26 + False + + + if_gain26 + 20 + + + iq_balance_mode26 + 0 + + + gain26 + 10 + + + ant27 + + + + bb_gain27 + 20 + + + bw27 + 0 + + + dc_offset_mode27 + 0 + + + corr27 + 0 + + + freq27 + 100e6 + + + gain_mode27 + False + + + if_gain27 + 20 + + + iq_balance_mode27 + 0 + + + gain27 + 10 + + + ant28 + + + + bb_gain28 + 20 + + + bw28 + 0 + + + dc_offset_mode28 + 0 + + + corr28 + 0 + + + freq28 + 100e6 + + + gain_mode28 + False + + + if_gain28 + 20 + + + iq_balance_mode28 + 0 + + + gain28 + 10 + + + ant29 + + + + bb_gain29 + 20 + + + bw29 + 0 + + + dc_offset_mode29 + 0 + + + corr29 + 0 + + + freq29 + 100e6 + + + gain_mode29 + False + + + if_gain29 + 20 + + + iq_balance_mode29 + 0 + + + gain29 + 10 + + + ant2 + + + + bb_gain2 + 20 + + + bw2 + 0 + + + dc_offset_mode2 + 0 + + + corr2 + 0 + + + freq2 + 100e6 + + + gain_mode2 + False + + + if_gain2 + 20 + + + iq_balance_mode2 + 0 + + + gain2 + 10 + + + ant30 + + + + bb_gain30 + 20 + + + bw30 + 0 + + + dc_offset_mode30 + 0 + + + corr30 + 0 + + + freq30 + 100e6 + + + gain_mode30 + False + + + if_gain30 + 20 + + + iq_balance_mode30 + 0 + + + gain30 + 10 + + + ant31 + + + + bb_gain31 + 20 + + + bw31 + 0 + + + dc_offset_mode31 + 0 + + + corr31 + 0 + + + freq31 + 100e6 + + + gain_mode31 + False + + + if_gain31 + 20 + + + iq_balance_mode31 + 0 + + + gain31 + 10 + + + ant3 + + + + bb_gain3 + 20 + + + bw3 + 0 + + + dc_offset_mode3 + 0 + + + corr3 + 0 + + + freq3 + 100e6 + + + gain_mode3 + False + + + if_gain3 + 20 + + + iq_balance_mode3 + 0 + + + gain3 + 10 + + + ant4 + + + + bb_gain4 + 20 + + + bw4 + 0 + + + dc_offset_mode4 + 0 + + + corr4 + 0 + + + freq4 + 100e6 + + + gain_mode4 + False + + + if_gain4 + 20 + + + iq_balance_mode4 + 0 + + + gain4 + 10 + + + ant5 + + + + bb_gain5 + 20 + + + bw5 + 0 + + + dc_offset_mode5 + 0 + + + corr5 + 0 + + + freq5 + 100e6 + + + gain_mode5 + False + + + if_gain5 + 20 + + + iq_balance_mode5 + 0 + + + gain5 + 10 + + + ant6 + + + + bb_gain6 + 20 + + + bw6 + 0 + + + dc_offset_mode6 + 0 + + + corr6 + 0 + + + freq6 + 100e6 + + + gain_mode6 + False + + + if_gain6 + 20 + + + iq_balance_mode6 + 0 + + + gain6 + 10 + + + ant7 + + + + bb_gain7 + 20 + + + bw7 + 0 + + + dc_offset_mode7 + 0 + + + corr7 + 0 + + + freq7 + 100e6 + + + gain_mode7 + False + + + if_gain7 + 20 + + + iq_balance_mode7 + 0 + + + gain7 + 10 + + + ant8 + + + + bb_gain8 + 20 + + + bw8 + 0 + + + dc_offset_mode8 + 0 + + + corr8 + 0 + + + freq8 + 100e6 + + + gain_mode8 + False + + + if_gain8 + 20 + + + iq_balance_mode8 + 0 + + + gain8 + 10 + + + ant9 + + + + bb_gain9 + 20 + + + bw9 + 0 + + + dc_offset_mode9 + 0 + + + corr9 + 0 + + + freq9 + 100e6 + + + gain_mode9 + False + + + if_gain9 + 20 + + + iq_balance_mode9 + 0 + + + gain9 + 10 + + + comment + + + + affinity + + + + args + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] + + + _enabled + 1 + + + _coordinate + (24, 256) + + + _rotation + 0 + + + id + osmosdr_source_0 + + + maxoutbuf + 0 + + + clock_source0 + + + + time_source0 + + + + clock_source1 + + + + time_source1 + + + + clock_source2 + + + + time_source2 + + + + clock_source3 + + + + time_source3 + + + + clock_source4 + + + + time_source4 + + + + clock_source5 + + + + time_source5 + + + + clock_source6 + + + + time_source6 + + + + clock_source7 + + + + time_source7 + + + + minoutbuf + 0 + + + nchan + 1 + + + num_mboards + 1 + + + type + fc32 + + + sample_rate + samp_rate_rx + + + sync + + + + + qtgui_freq_sink_x + + autoscale + False + + + average + 1.0 + + + axislabels + True + + + bw + samp_rate_rx + + + alias + + + + fc + 0 + + + comment + + + + ctrlpanel + True + + + affinity + + + + _enabled + 0 + + + fftsize + 1024 + + + _coordinate + (792, 28) + + + gui_hint + + + + _rotation + 0 + + + grid + True + + + id + qtgui_freq_sink_x_0 + + + legend + True + + + alpha1 + 1.0 + + + color1 + "blue" + + + label1 + + + + width1 + 1 + + + alpha10 + 1.0 + + + color10 + "dark blue" + + + label10 + + + + width10 + 1 + + + alpha2 + 1.0 + + + color2 + "red" + + + label2 + + + + width2 + 1 + + + alpha3 + 1.0 + + + color3 + "green" + + + label3 + + + + width3 + 1 + + + alpha4 + 1.0 + + + color4 + "black" + + + label4 + + + + width4 + 1 + + + alpha5 + 1.0 + + + color5 + "cyan" + + + label5 + + + + width5 + 1 + + + alpha6 + 1.0 + + + color6 + "magenta" + + + label6 + + + + width6 + 1 + + + alpha7 + 1.0 + + + color7 + "yellow" + + + label7 + + + + width7 + 1 + + + alpha8 + 1.0 + + + color8 + "dark red" + + + label8 + + + + width8 + 1 + + + alpha9 + 1.0 + + + color9 + "dark green" + + + label9 + + + + width9 + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + name + "" + + + nconnections + 1 + + + showports + True + + + freqhalf + True + + + tr_chan + 0 + + + tr_level + 0.0 + + + tr_mode + qtgui.TRIG_MODE_FREE + + + tr_tag + "" + + + type + complex + + + update_time + 0.01 + + + wintype + firdes.WIN_BLACKMAN_hARRIS + + + label + Relative Gain + + + ymax + 10 + + + ymin + -140 + + + units + dB + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 780) + + + _rotation + 0 + + + id + rigctl_port + + + label + + + + short_id + + + + type + intx + + + value + 4532 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 700) + + + _rotation + 0 + + + id + rx_freq + + + label + + + + short_id + + + + type + eng_float + + + value + 100e6 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (64, 484) + + + _rotation + 0 + + + id + rx_sdr_device + + + label + + + + short_id + + + + type + string + + + value + usrpb200 + + + + satnogs_doppler_correction_cc + + alias + + + + comment + + + + affinity + + + + corrections_per_sec + doppler_correction_per_sec + + + _enabled + 1 + + + _coordinate + (304, 256) + + + _rotation + 0 + + + id + satnogs_doppler_correction_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + sampling_rate + samp_rate_rx + + + target_freq + rx_freq + + + + satnogs_tcp_rigctl_msg_source + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (24, 164) + + + _rotation + 0 + + + id + satnogs_tcp_rigctl_msg_source_0 + + + addr + "127.0.0.1" + + + port + rigctl_port + + + mtu + 1500 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + analog_sig_source_x_0 + blocks_multiply_xx_0 + 0 + 0 + + + blocks_multiply_xx_0 + qtgui_freq_sink_x_0 + 0 + 0 + + + freq_xlating_fir_filter_xxx_0 + blocks_file_sink_0 + 0 + 0 + + + osmosdr_source_0 + blocks_multiply_xx_0 + 0 + 1 + + + osmosdr_source_0 + satnogs_doppler_correction_cc_0 + 0 + 0 + + + satnogs_doppler_correction_cc_0 + freq_xlating_fir_filter_xxx_0 + 0 + 0 + + + satnogs_tcp_rigctl_msg_source_0 + satnogs_doppler_correction_cc_0 + freq + freq + + diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index 3eccf05..be266ed 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,20 +5,9 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Wed Oct 12 21:16:27 2016 +# Generated: Mon Oct 17 19:24:53 2016 ################################################## -if __name__ == '__main__': - import ctypes - import sys - if sys.platform.startswith('linux'): - try: - x11 = ctypes.cdll.LoadLibrary('libX11.so') - x11.XInitThreads() - except: - print "Warning: failed to XInitThreads()" - -from PyQt4 import Qt from gnuradio import analog from gnuradio import blocks from gnuradio import eng_notation @@ -30,40 +19,21 @@ from gnuradio.filter import pfb from optparse import OptionParser import osmosdr import satnogs -import sys import time -class satnogs_fm_demod(gr.top_block, Qt.QWidget): +class satnogs_fm_demod(gr.top_block): - def __init__(self, file_path="test.wav", lo_offset=100e3, rx_freq=100e6, rx_sdr_device="usrpb200"): + def __init__(self, doppler_correction_per_sec=1000, file_path="test.wav", lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device="usrpb200"): gr.top_block.__init__(self, "FM Generic Demodulation") - Qt.QWidget.__init__(self) - self.setWindowTitle("FM Generic Demodulation") - try: - self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) - except: - pass - self.top_scroll_layout = Qt.QVBoxLayout() - self.setLayout(self.top_scroll_layout) - self.top_scroll = Qt.QScrollArea() - self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) - self.top_scroll_layout.addWidget(self.top_scroll) - self.top_scroll.setWidgetResizable(True) - self.top_widget = Qt.QWidget() - self.top_scroll.setWidget(self.top_widget) - self.top_layout = Qt.QVBoxLayout(self.top_widget) - self.top_grid_layout = Qt.QGridLayout() - self.top_layout.addLayout(self.top_grid_layout) - - self.settings = Qt.QSettings("GNU Radio", "satnogs_fm_demod") - self.restoreGeometry(self.settings.value("geometry").toByteArray()) ################################################## # Parameters ################################################## + self.doppler_correction_per_sec = doppler_correction_per_sec self.file_path = file_path self.lo_offset = lo_offset + self.rigctl_port = rigctl_port self.rx_freq = rx_freq self.rx_sdr_device = rx_sdr_device @@ -83,8 +53,8 @@ class satnogs_fm_demod(gr.top_block, Qt.QWidget): ################################################## # Blocks ################################################## - self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", 4532, 1500) - self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, 1000) + self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, 1500) + self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation), taps=(firdes.low_pass_2(32, 32, 0.8, 0.1, 100)), @@ -123,10 +93,11 @@ class satnogs_fm_demod(gr.top_block, Qt.QWidget): self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.satnogs_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) - def closeEvent(self, event): - self.settings = Qt.QSettings("GNU Radio", "satnogs_fm_demod") - self.settings.setValue("geometry", self.saveGeometry()) - event.accept() + def get_doppler_correction_per_sec(self): + return self.doppler_correction_per_sec + + def set_doppler_correction_per_sec(self, doppler_correction_per_sec): + self.doppler_correction_per_sec = doppler_correction_per_sec def get_file_path(self): return self.file_path @@ -143,6 +114,12 @@ class satnogs_fm_demod(gr.top_block, Qt.QWidget): self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + def get_rigctl_port(self): + return self.rigctl_port + + def set_rigctl_port(self, rigctl_port): + self.rigctl_port = rigctl_port + def get_rx_freq(self): return self.rx_freq @@ -218,12 +195,18 @@ class satnogs_fm_demod(gr.top_block, Qt.QWidget): def argument_parser(): description = 'A generic FM demodulation block' parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) + parser.add_option( + "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000, + help="Set doppler_correction_per_sec [default=%default]") parser.add_option( "", "--file-path", dest="file_path", type="string", default="test.wav", help="Set file_path [default=%default]") parser.add_option( "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), help="Set lo_offset [default=%default]") + parser.add_option( + "", "--rigctl-port", dest="rigctl_port", type="intx", default=4532, + help="Set rigctl_port [default=%default]") parser.add_option( "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6), help="Set rx_freq [default=%default]") @@ -237,21 +220,9 @@ def main(top_block_cls=satnogs_fm_demod, options=None): if options is None: options, _ = argument_parser().parse_args() - from distutils.version import StrictVersion - if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): - style = gr.prefs().get_string('qtgui', 'style', 'raster') - Qt.QApplication.setGraphicsSystem(style) - qapp = Qt.QApplication(sys.argv) - - tb = top_block_cls(file_path=options.file_path, lo_offset=options.lo_offset, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device) + tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device) tb.start() - tb.show() - - def quitting(): - tb.stop() - tb.wait() - qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting) - qapp.exec_() + tb.wait() if __name__ == '__main__': diff --git a/apps/flowgraphs/satnogs_generic_iq_receiver.py b/apps/flowgraphs/satnogs_generic_iq_receiver.py new file mode 100755 index 0000000..a9a25e0 --- /dev/null +++ b/apps/flowgraphs/satnogs_generic_iq_receiver.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: Generic IQ samples receiver +# Author: Manolis Surligas (surligas@gmail.com) +# Description: A generic FM demodulation block +# Generated: Mon Oct 17 19:32:33 2016 +################################################## + +from gnuradio import blocks +from gnuradio import eng_notation +from gnuradio import filter +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.filter import firdes +from optparse import OptionParser +import osmosdr +import satnogs +import time + + +class satnogs_generic_iq_receiver(gr.top_block): + + def __init__(self, doppler_correction_per_sec=1000, file_path="test.wav", lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device="usrpb200"): + gr.top_block.__init__(self, "Generic IQ samples receiver") + + ################################################## + # Parameters + ################################################## + self.doppler_correction_per_sec = doppler_correction_per_sec + self.file_path = file_path + self.lo_offset = lo_offset + self.rigctl_port = rigctl_port + self.rx_freq = rx_freq + self.rx_sdr_device = rx_sdr_device + + ################################################## + # Variables + ################################################## + self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] + self.decimation_rx = decimation_rx = satnogs.fm_demod_settings[rx_sdr_device]['decimation_rx'] + + self.taps = taps = firdes.low_pass(12.0, samp_rate_rx, 100e3, 60000, firdes.WIN_HAMMING, 6.76) + + self.quadrature_rate = quadrature_rate = samp_rate_rx / decimation_rx + self.audio_samp_rate = audio_samp_rate = 44100 + self.audio_gain = audio_gain = satnogs.fm_demod_settings[rx_sdr_device]['audio_gain'] + self.audio_decimation = audio_decimation = 2 + + ################################################## + # Blocks + ################################################## + self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, 1500) + self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) + self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) + self.osmosdr_source_0.set_sample_rate(samp_rate_rx) + self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) + self.osmosdr_source_0.set_freq_corr(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_iq_balance_mode(0, 0) + self.osmosdr_source_0.set_gain_mode(False, 0) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0) + self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) + + self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(decimation_rx, (taps), lo_offset, samp_rate_rx) + self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_gr_complex*1, file_path, False) + self.blocks_file_sink_0.set_unbuffered(True) + + ################################################## + # Connections + ################################################## + self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_doppler_correction_cc_0, 'freq')) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blocks_file_sink_0, 0)) + self.connect((self.osmosdr_source_0, 0), (self.satnogs_doppler_correction_cc_0, 0)) + self.connect((self.satnogs_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + + def get_doppler_correction_per_sec(self): + return self.doppler_correction_per_sec + + def set_doppler_correction_per_sec(self, doppler_correction_per_sec): + self.doppler_correction_per_sec = doppler_correction_per_sec + + def get_file_path(self): + return self.file_path + + def set_file_path(self, file_path): + self.file_path = file_path + self.blocks_file_sink_0.open(self.file_path) + + def get_lo_offset(self): + return self.lo_offset + + def set_lo_offset(self, lo_offset): + self.lo_offset = lo_offset + self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) + self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + + def get_rigctl_port(self): + return self.rigctl_port + + def set_rigctl_port(self, rigctl_port): + self.rigctl_port = rigctl_port + + def get_rx_freq(self): + return self.rx_freq + + def set_rx_freq(self, rx_freq): + self.rx_freq = rx_freq + self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) + + def get_rx_sdr_device(self): + return self.rx_sdr_device + + def set_rx_sdr_device(self, rx_sdr_device): + self.rx_sdr_device = rx_sdr_device + self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) + self.set_decimation_rx(satnogs.fm_demod_settings[self.rx_sdr_device]['decimation_rx']) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0) + self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain']) + + def get_samp_rate_rx(self): + return self.samp_rate_rx + + def set_samp_rate_rx(self, samp_rate_rx): + self.samp_rate_rx = samp_rate_rx + self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx) + self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0) + + def get_decimation_rx(self): + return self.decimation_rx + + def set_decimation_rx(self, decimation_rx): + self.decimation_rx = decimation_rx + self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.freq_xlating_fir_filter_xxx_0.set_taps((self.taps)) + + def get_quadrature_rate(self): + return self.quadrature_rate + + def set_quadrature_rate(self, quadrature_rate): + self.quadrature_rate = quadrature_rate + + def get_audio_samp_rate(self): + return self.audio_samp_rate + + def set_audio_samp_rate(self, audio_samp_rate): + self.audio_samp_rate = audio_samp_rate + + def get_audio_gain(self): + return self.audio_gain + + def set_audio_gain(self, audio_gain): + self.audio_gain = audio_gain + + def get_audio_decimation(self): + return self.audio_decimation + + def set_audio_decimation(self, audio_decimation): + self.audio_decimation = audio_decimation + + +def argument_parser(): + description = 'A generic FM demodulation block' + parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) + parser.add_option( + "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000, + help="Set doppler_correction_per_sec [default=%default]") + parser.add_option( + "", "--file-path", dest="file_path", type="string", default="test.wav", + help="Set file_path [default=%default]") + parser.add_option( + "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), + help="Set lo_offset [default=%default]") + parser.add_option( + "", "--rigctl-port", dest="rigctl_port", type="intx", default=4532, + help="Set rigctl_port [default=%default]") + parser.add_option( + "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6), + help="Set rx_freq [default=%default]") + parser.add_option( + "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default="usrpb200", + help="Set rx_sdr_device [default=%default]") + return parser + + +def main(top_block_cls=satnogs_generic_iq_receiver, options=None): + if options is None: + options, _ = argument_parser().parse_args() + + tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device) + tb.start() + tb.wait() + + +if __name__ == '__main__': + main() From f320d841ab7d4c104724ff36601f953421e82e5c Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 21 Oct 2016 23:11:29 +0300 Subject: [PATCH 06/26] Add supoort to the rigctl message source to work as client Start also the LEO channelizer. It is not yet functional. --- CMakeLists.txt | 11 +- apps/flowgraphs/fm_demod.grc | 18 +- apps/flowgraphs/satnogs_fm_demod.py | 10 +- cmake/Modules/FindNova.cmake | 26 + grc/CMakeLists.txt | 1 + grc/satnogs_leo_channel.xml | 38 ++ grc/satnogs_tcp_rigctl_msg_source.xml | 25 +- include/satnogs/CMakeLists.txt | 3 +- include/satnogs/leo_channel.h | 722 ++++++++++++++++++++++++ include/satnogs/tcp_rigctl_msg_source.h | 10 +- lib/CMakeLists.txt | 4 +- lib/leo_channel_impl.cc | 79 +++ lib/leo_channel_impl.h | 52 ++ lib/tcp_rigctl_msg_source_impl.cc | 298 +++++++--- lib/tcp_rigctl_msg_source_impl.h | 10 +- swig/satnogs_debug_swig.i | 4 + 16 files changed, 1201 insertions(+), 110 deletions(-) create mode 100644 cmake/Modules/FindNova.cmake create mode 100644 grc/satnogs_leo_channel.xml create mode 100644 include/satnogs/leo_channel.h create mode 100644 lib/leo_channel_impl.cc create mode 100644 lib/leo_channel_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 53ea76d..4603054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,14 @@ find_package (Threads REQUIRED) find_package(CppUnit) find_package(Doxygen) +######################################################################## +# Find gr-satnogs external build dependencies +######################################################################## +find_package(Nova) +if(NOT NOVA_FOUND) + message(FATAL_ERROR "libnova required to compile satnogs") +endif() + # Search for GNU Radio and its components and versions. Add any # components required to the list of GR_REQUIRED_COMPONENTS (in all # caps such as FILTER or FFT) and change the version to the minimum @@ -140,7 +148,7 @@ endif(DOXYGEN_FOUND) # Include or not into the module blocks for debugging ######################################################################## if(NOT INCLUDE_DEBUG_BLOCKS) - set(INCLUDE_DEBUG_BLOCKS OFF CACHE BOOL + set(INCLUDE_DEBUG_BLOCKS ON CACHE BOOL "Disable blocks that are used for debugging purposes") endif() @@ -155,6 +163,7 @@ include_directories( ${Boost_INCLUDE_DIRS} ${CPPUNIT_INCLUDE_DIRS} ${GNURADIO_ALL_INCLUDE_DIRS} + ${NOVA_INCLUDE_DIRS} ) link_directories( diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index 64f1ccd..08a8194 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -2047,7 +2047,7 @@ we shift the LO a little further _coordinate - (24, 256) + (24, 264) _rotation @@ -2726,10 +2726,6 @@ we shift the LO a little further addr "127.0.0.1" - - port - rigctl_port - mtu 1500 @@ -2742,6 +2738,18 @@ we shift the LO a little further minoutbuf 0 + + mode + False + + + port + rigctl_port + + + interval + 1000 + analog_sig_source_x_0 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index be266ed..42d51dc 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Oct 17 19:24:53 2016 +# Generated: Fri Oct 21 22:22:13 2016 ################################################## from gnuradio import analog @@ -24,7 +24,7 @@ import time class satnogs_fm_demod(gr.top_block): - def __init__(self, doppler_correction_per_sec=1000, file_path="test.wav", lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device="usrpb200"): + def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200'): gr.top_block.__init__(self, "FM Generic Demodulation") ################################################## @@ -53,7 +53,7 @@ class satnogs_fm_demod(gr.top_block): ################################################## # Blocks ################################################## - self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, 1500) + self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation), @@ -199,7 +199,7 @@ def argument_parser(): "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000, help="Set doppler_correction_per_sec [default=%default]") parser.add_option( - "", "--file-path", dest="file_path", type="string", default="test.wav", + "", "--file-path", dest="file_path", type="string", default='test.wav', help="Set file_path [default=%default]") parser.add_option( "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), @@ -211,7 +211,7 @@ def argument_parser(): "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6), help="Set rx_freq [default=%default]") parser.add_option( - "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default="usrpb200", + "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200', help="Set rx_sdr_device [default=%default]") return parser diff --git a/cmake/Modules/FindNova.cmake b/cmake/Modules/FindNova.cmake new file mode 100644 index 0000000..ab45e18 --- /dev/null +++ b/cmake/Modules/FindNova.cmake @@ -0,0 +1,26 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_NOVA Nova) + +FIND_PATH( + NOVA_INCLUDE_DIRS + NAMES libnova/libnova.h + HINTS $ENV{NOVA_DIR}/include + ${PC_NOVA_INCLUDEDIR} + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + NOVA_LIBRARIES + NAMES nova + HINTS $ENV{NOVA_DIR}/lib + ${PC_NOVA_LIBDIR} + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NOVA DEFAULT_MSG NOVA_LIBRARIES NOVA_INCLUDE_DIRS) +MARK_AS_ADVANCED(NOVA_LIBRARIES NOVA_INCLUDE_DIRS) \ No newline at end of file diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index a9f297a..a8f0ba5 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -21,6 +21,7 @@ list(APPEND debug_blocks satnogs_morse_debug_source.xml satnogs_debug_msg_source.xml satnogs_debug_msg_source_raw.xml + satnogs_leo_channel.xml ) list(APPEND enabled_blocks diff --git a/grc/satnogs_leo_channel.xml b/grc/satnogs_leo_channel.xml new file mode 100644 index 0000000..7df7ae5 --- /dev/null +++ b/grc/satnogs_leo_channel.xml @@ -0,0 +1,38 @@ + + + leo_channel + satnogs_leo_channel + [satnogs] + import satnogs + satnogs.leo_channel($freq, $freq_shifts_per_sec) + + + ... + ... + ... + + + + + in + + + + + + out + + + diff --git a/grc/satnogs_tcp_rigctl_msg_source.xml b/grc/satnogs_tcp_rigctl_msg_source.xml index 8e2d886..afee538 100644 --- a/grc/satnogs_tcp_rigctl_msg_source.xml +++ b/grc/satnogs_tcp_rigctl_msg_source.xml @@ -4,7 +4,7 @@ satnogs_tcp_rigctl_msg_source satnogs import satnogs - satnogs.tcp_rigctl_msg_source($addr, $port, $mtu) + satnogs.tcp_rigctl_msg_source($addr, $port, $mode, $interval, $mtu) IP Address @@ -14,11 +14,32 @@ - Listen port + Port port 16886 int + + + Mode + mode + enum + + + + + + Update interval (ms) + interval + 1000 + int + MTU diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 5e29764..c91e88f 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND DEBUG_HEADER_FILES morse_debug_source.h debug_msg_source_raw.h debug_msg_source.h + leo_channel.h ) list(APPEND HEADER_FILES @@ -61,5 +62,5 @@ endif() install(FILES ${HEADER_FILES} - DESTINATION include/satnogs + DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/leo_channel.h b/include/satnogs/leo_channel.h new file mode 100644 index 0000000..2d71ab5 --- /dev/null +++ b/include/satnogs/leo_channel.h @@ -0,0 +1,722 @@ +/* -*- c++ -*- */ +/* GNU GENERAL PUBLIC LICENSE + * Version 3, 29 June 2007 + * + * Copyright (C) 2007 Free Software Foundation, Inc. + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + * + * Preamble + * + * The GNU General Public License is a free, copyleft license for + * software and other kinds of works. + * + * The licenses for most software and other practical works are designed + * to take away your freedom to share and change the works. By contrast, + * the GNU General Public License is intended to guarantee your freedom to + * share and change all versions of a program--to make sure it remains free + * software for all its users. We, the Free Software Foundation, use the + * GNU General Public License for most of our software; it applies also to + * any other work released this way by its authors. You can apply it to + * your programs, too. + * + * When we speak of free software, we are referring to freedom, not + * price. Our General Public Licenses are designed to make sure that you + * have the freedom to distribute copies of free software (and charge for + * them if you wish), that you receive source code or can get it if you + * want it, that you can change the software or use pieces of it in new + * free programs, and that you know you can do these things. + * + * To protect your rights, we need to prevent others from denying you + * these rights or asking you to surrender the rights. Therefore, you have + * certain responsibilities if you distribute copies of the software, or if + * you modify it: responsibilities to respect the freedom of others. + * + * For example, if you distribute copies of such a program, whether + * gratis or for a fee, you must pass on to the recipients the same + * freedoms that you received. You must make sure that they, too, receive + * or can get the source code. And you must show them these terms so they + * know their rights. + * + * Developers that use the GNU GPL protect your rights with two steps: + * (1) assert copyright on the software, and (2) offer you this License + * giving you legal permission to copy, distribute and/or modify it. + * + * For the developers' and authors' protection, the GPL clearly explains + * that there is no warranty for this free software. For both users' and + * authors' sake, the GPL requires that modified versions be marked as + * changed, so that their problems will not be attributed erroneously to + * authors of previous versions. + * + * Some devices are designed to deny users access to install or run + * modified versions of the software inside them, although the manufacturer + * can do so. This is fundamentally incompatible with the aim of + * protecting users' freedom to change the software. The systematic + * pattern of such abuse occurs in the area of products for individuals to + * use, which is precisely where it is most unacceptable. Therefore, we + * have designed this version of the GPL to prohibit the practice for those + * products. If such problems arise substantially in other domains, we + * stand ready to extend this provision to those domains in future versions + * of the GPL, as needed to protect the freedom of users. + * + * Finally, every program is threatened constantly by software patents. + * States should not allow patents to restrict development and use of + * software on general-purpose computers, but in those that do, we wish to + * avoid the special danger that patents applied to a free program could + * make it effectively proprietary. To prevent this, the GPL assures that + * patents cannot be used to render the program non-free. + * + * The precise terms and conditions for copying, distribution and + * modification follow. + * + * TERMS AND CONDITIONS + * + * 0. Definitions. + * + * "This License" refers to version 3 of the GNU General Public License. + * + * "Copyright" also means copyright-like laws that apply to other kinds of + * works, such as semiconductor masks. + * + * "The Program" refers to any copyrightable work licensed under this + * License. Each licensee is addressed as "you". "Licensees" and + * "recipients" may be individuals or organizations. + * + * To "modify" a work means to copy from or adapt all or part of the work + * in a fashion requiring copyright permission, other than the making of an + * exact copy. The resulting work is called a "modified version" of the + * earlier work or a work "based on" the earlier work. + * + * A "covered work" means either the unmodified Program or a work based + * on the Program. + * + * To "propagate" a work means to do anything with it that, without + * permission, would make you directly or secondarily liable for + * infringement under applicable copyright law, except executing it on a + * computer or modifying a private copy. Propagation includes copying, + * distribution (with or without modification), making available to the + * public, and in some countries other activities as well. + * + * To "convey" a work means any kind of propagation that enables other + * parties to make or receive copies. Mere interaction with a user through + * a computer network, with no transfer of a copy, is not conveying. + * + * An interactive user interface displays "Appropriate Legal Notices" + * to the extent that it includes a convenient and prominently visible + * feature that (1) displays an appropriate copyright notice, and (2) + * tells the user that there is no warranty for the work (except to the + * extent that warranties are provided), that licensees may convey the + * work under this License, and how to view a copy of this License. If + * the interface presents a list of user commands or options, such as a + * menu, a prominent item in the list meets this criterion. + * + * 1. Source Code. + * + * The "source code" for a work means the preferred form of the work + * for making modifications to it. "Object code" means any non-source + * form of a work. + * + * A "Standard Interface" means an interface that either is an official + * standard defined by a recognized standards body, or, in the case of + * interfaces specified for a particular programming language, one that + * is widely used among developers working in that language. + * + * The "System Libraries" of an executable work include anything, other + * than the work as a whole, that (a) is included in the normal form of + * packaging a Major Component, but which is not part of that Major + * Component, and (b) serves only to enable use of the work with that + * Major Component, or to implement a Standard Interface for which an + * implementation is available to the public in source code form. A + * "Major Component", in this context, means a major essential component + * (kernel, window system, and so on) of the specific operating system + * (if any) on which the executable work runs, or a compiler used to + * produce the work, or an object code interpreter used to run it. + * + * The "Corresponding Source" for a work in object code form means all + * the source code needed to generate, install, and (for an executable + * work) run the object code and to modify the work, including scripts to + * control those activities. However, it does not include the work's + * System Libraries, or general-purpose tools or generally available free + * programs which are used unmodified in performing those activities but + * which are not part of the work. For example, Corresponding Source + * includes interface definition files associated with source files for + * the work, and the source code for shared libraries and dynamically + * linked subprograms that the work is specifically designed to require, + * such as by intimate data communication or control flow between those + * subprograms and other parts of the work. + * + * The Corresponding Source need not include anything that users + * can regenerate automatically from other parts of the Corresponding + * Source. + * + * The Corresponding Source for a work in source code form is that + * same work. + * + * 2. Basic Permissions. + * + * All rights granted under this License are granted for the term of + * copyright on the Program, and are irrevocable provided the stated + * conditions are met. This License explicitly affirms your unlimited + * permission to run the unmodified Program. The output from running a + * covered work is covered by this License only if the output, given its + * content, constitutes a covered work. This License acknowledges your + * rights of fair use or other equivalent, as provided by copyright law. + * + * You may make, run and propagate covered works that you do not + * convey, without conditions so long as your license otherwise remains + * in force. You may convey covered works to others for the sole purpose + * of having them make modifications exclusively for you, or provide you + * with facilities for running those works, provided that you comply with + * the terms of this License in conveying all material for which you do + * not control copyright. Those thus making or running the covered works + * for you must do so exclusively on your behalf, under your direction + * and control, on terms that prohibit them from making any copies of + * your copyrighted material outside their relationship with you. + * + * Conveying under any other circumstances is permitted solely under + * the conditions stated below. Sublicensing is not allowed; section 10 + * makes it unnecessary. + * + * 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + * + * No covered work shall be deemed part of an effective technological + * measure under any applicable law fulfilling obligations under article + * 11 of the WIPO copyright treaty adopted on 20 December 1996, or + * similar laws prohibiting or restricting circumvention of such + * measures. + * + * When you convey a covered work, you waive any legal power to forbid + * circumvention of technological measures to the extent such circumvention + * is effected by exercising rights under this License with respect to + * the covered work, and you disclaim any intention to limit operation or + * modification of the work as a means of enforcing, against the work's + * users, your or third parties' legal rights to forbid circumvention of + * technological measures. + * + * 4. Conveying Verbatim Copies. + * + * You may convey verbatim copies of the Program's source code as you + * receive it, in any medium, provided that you conspicuously and + * appropriately publish on each copy an appropriate copyright notice; + * keep intact all notices stating that this License and any + * non-permissive terms added in accord with section 7 apply to the code; + * keep intact all notices of the absence of any warranty; and give all + * recipients a copy of this License along with the Program. + * + * You may charge any price or no price for each copy that you convey, + * and you may offer support or warranty protection for a fee. + * + * 5. Conveying Modified Source Versions. + * + * You may convey a work based on the Program, or the modifications to + * produce it from the Program, in the form of source code under the + * terms of section 4, provided that you also meet all of these conditions: + * + * a) The work must carry prominent notices stating that you modified + * it, and giving a relevant date. + * + * b) The work must carry prominent notices stating that it is + * released under this License and any conditions added under section + * 7. This requirement modifies the requirement in section 4 to + * "keep intact all notices". + * + * c) You must license the entire work, as a whole, under this + * License to anyone who comes into possession of a copy. This + * License will therefore apply, along with any applicable section 7 + * additional terms, to the whole of the work, and all its parts, + * regardless of how they are packaged. This License gives no + * permission to license the work in any other way, but it does not + * invalidate such permission if you have separately received it. + * + * d) If the work has interactive user interfaces, each must display + * Appropriate Legal Notices; however, if the Program has interactive + * interfaces that do not display Appropriate Legal Notices, your + * work need not make them do so. + * + * A compilation of a covered work with other separate and independent + * works, which are not by their nature extensions of the covered work, + * and which are not combined with it such as to form a larger program, + * in or on a volume of a storage or distribution medium, is called an + * "aggregate" if the compilation and its resulting copyright are not + * used to limit the access or legal rights of the compilation's users + * beyond what the individual works permit. Inclusion of a covered work + * in an aggregate does not cause this License to apply to the other + * parts of the aggregate. + * + * 6. Conveying Non-Source Forms. + * + * You may convey a covered work in object code form under the terms + * of sections 4 and 5, provided that you also convey the + * machine-readable Corresponding Source under the terms of this License, + * in one of these ways: + * + * a) Convey the object code in, or embodied in, a physical product + * (including a physical distribution medium), accompanied by the + * Corresponding Source fixed on a durable physical medium + * customarily used for software interchange. + * + * b) Convey the object code in, or embodied in, a physical product + * (including a physical distribution medium), accompanied by a + * written offer, valid for at least three years and valid for as + * long as you offer spare parts or customer support for that product + * model, to give anyone who possesses the object code either (1) a + * copy of the Corresponding Source for all the software in the + * product that is covered by this License, on a durable physical + * medium customarily used for software interchange, for a price no + * more than your reasonable cost of physically performing this + * conveying of source, or (2) access to copy the + * Corresponding Source from a network server at no charge. + * + * c) Convey individual copies of the object code with a copy of the + * written offer to provide the Corresponding Source. This + * alternative is allowed only occasionally and noncommercially, and + * only if you received the object code with such an offer, in accord + * with subsection 6b. + * + * d) Convey the object code by offering access from a designated + * place (gratis or for a charge), and offer equivalent access to the + * Corresponding Source in the same way through the same place at no + * further charge. You need not require recipients to copy the + * Corresponding Source along with the object code. If the place to + * copy the object code is a network server, the Corresponding Source + * may be on a different server (operated by you or a third party) + * that supports equivalent copying facilities, provided you maintain + * clear directions next to the object code saying where to find the + * Corresponding Source. Regardless of what server hosts the + * Corresponding Source, you remain obligated to ensure that it is + * available for as long as needed to satisfy these requirements. + * + * e) Convey the object code using peer-to-peer transmission, provided + * you inform other peers where the object code and Corresponding + * Source of the work are being offered to the general public at no + * charge under subsection 6d. + * + * A separable portion of the object code, whose source code is excluded + * from the Corresponding Source as a System Library, need not be + * included in conveying the object code work. + * + * A "User Product" is either (1) a "consumer product", which means any + * tangible personal property which is normally used for personal, family, + * or household purposes, or (2) anything designed or sold for incorporation + * into a dwelling. In determining whether a product is a consumer product, + * doubtful cases shall be resolved in favor of coverage. For a particular + * product received by a particular user, "normally used" refers to a + * typical or common use of that class of product, regardless of the status + * of the particular user or of the way in which the particular user + * actually uses, or expects or is expected to use, the product. A product + * is a consumer product regardless of whether the product has substantial + * commercial, industrial or non-consumer uses, unless such uses represent + * the only significant mode of use of the product. + * + * "Installation Information" for a User Product means any methods, + * procedures, authorization keys, or other information required to install + * and execute modified versions of a covered work in that User Product from + * a modified version of its Corresponding Source. The information must + * suffice to ensure that the continued functioning of the modified object + * code is in no case prevented or interfered with solely because + * modification has been made. + * + * If you convey an object code work under this section in, or with, or + * specifically for use in, a User Product, and the conveying occurs as + * part of a transaction in which the right of possession and use of the + * User Product is transferred to the recipient in perpetuity or for a + * fixed term (regardless of how the transaction is characterized), the + * Corresponding Source conveyed under this section must be accompanied + * by the Installation Information. But this requirement does not apply + * if neither you nor any third party retains the ability to install + * modified object code on the User Product (for example, the work has + * been installed in ROM). + * + * The requirement to provide Installation Information does not include a + * requirement to continue to provide support service, warranty, or updates + * for a work that has been modified or installed by the recipient, or for + * the User Product in which it has been modified or installed. Access to a + * network may be denied when the modification itself materially and + * adversely affects the operation of the network or violates the rules and + * protocols for communication across the network. + * + * Corresponding Source conveyed, and Installation Information provided, + * in accord with this section must be in a format that is publicly + * documented (and with an implementation available to the public in + * source code form), and must require no special password or key for + * unpacking, reading or copying. + * + * 7. Additional Terms. + * + * "Additional permissions" are terms that supplement the terms of this + * License by making exceptions from one or more of its conditions. + * Additional permissions that are applicable to the entire Program shall + * be treated as though they were included in this License, to the extent + * that they are valid under applicable law. If additional permissions + * apply only to part of the Program, that part may be used separately + * under those permissions, but the entire Program remains governed by + * this License without regard to the additional permissions. + * + * When you convey a copy of a covered work, you may at your option + * remove any additional permissions from that copy, or from any part of + * it. (Additional permissions may be written to require their own + * removal in certain cases when you modify the work.) You may place + * additional permissions on material, added by you to a covered work, + * for which you have or can give appropriate copyright permission. + * + * Notwithstanding any other provision of this License, for material you + * add to a covered work, you may (if authorized by the copyright holders of + * that material) supplement the terms of this License with terms: + * + * a) Disclaiming warranty or limiting liability differently from the + * terms of sections 15 and 16 of this License; or + * + * b) Requiring preservation of specified reasonable legal notices or + * author attributions in that material or in the Appropriate Legal + * Notices displayed by works containing it; or + * + * c) Prohibiting misrepresentation of the origin of that material, or + * requiring that modified versions of such material be marked in + * reasonable ways as different from the original version; or + * + * d) Limiting the use for publicity purposes of names of licensors or + * authors of the material; or + * + * e) Declining to grant rights under trademark law for use of some + * trade names, trademarks, or service marks; or + * + * f) Requiring indemnification of licensors and authors of that + * material by anyone who conveys the material (or modified versions of + * it) with contractual assumptions of liability to the recipient, for + * any liability that these contractual assumptions directly impose on + * those licensors and authors. + * + * All other non-permissive additional terms are considered "further + * restrictions" within the meaning of section 10. If the Program as you + * received it, or any part of it, contains a notice stating that it is + * governed by this License along with a term that is a further + * restriction, you may remove that term. If a license document contains + * a further restriction but permits relicensing or conveying under this + * License, you may add to a covered work material governed by the terms + * of that license document, provided that the further restriction does + * not survive such relicensing or conveying. + * + * If you add terms to a covered work in accord with this section, you + * must place, in the relevant source files, a statement of the + * additional terms that apply to those files, or a notice indicating + * where to find the applicable terms. + * + * Additional terms, permissive or non-permissive, may be stated in the + * form of a separately written license, or stated as exceptions; + * the above requirements apply either way. + * + * 8. Termination. + * + * You may not propagate or modify a covered work except as expressly + * provided under this License. Any attempt otherwise to propagate or + * modify it is void, and will automatically terminate your rights under + * this License (including any patent licenses granted under the third + * paragraph of section 11). + * + * However, if you cease all violation of this License, then your + * license from a particular copyright holder is reinstated (a) + * provisionally, unless and until the copyright holder explicitly and + * finally terminates your license, and (b) permanently, if the copyright + * holder fails to notify you of the violation by some reasonable means + * prior to 60 days after the cessation. + * + * Moreover, your license from a particular copyright holder is + * reinstated permanently if the copyright holder notifies you of the + * violation by some reasonable means, this is the first time you have + * received notice of violation of this License (for any work) from that + * copyright holder, and you cure the violation prior to 30 days after + * your receipt of the notice. + * + * Termination of your rights under this section does not terminate the + * licenses of parties who have received copies or rights from you under + * this License. If your rights have been terminated and not permanently + * reinstated, you do not qualify to receive new licenses for the same + * material under section 10. + * + * 9. Acceptance Not Required for Having Copies. + * + * You are not required to accept this License in order to receive or + * run a copy of the Program. Ancillary propagation of a covered work + * occurring solely as a consequence of using peer-to-peer transmission + * to receive a copy likewise does not require acceptance. However, + * nothing other than this License grants you permission to propagate or + * modify any covered work. These actions infringe copyright if you do + * not accept this License. Therefore, by modifying or propagating a + * covered work, you indicate your acceptance of this License to do so. + * + * 10. Automatic Licensing of Downstream Recipients. + * + * Each time you convey a covered work, the recipient automatically + * receives a license from the original licensors, to run, modify and + * propagate that work, subject to this License. You are not responsible + * for enforcing compliance by third parties with this License. + * + * An "entity transaction" is a transaction transferring control of an + * organization, or substantially all assets of one, or subdividing an + * organization, or merging organizations. If propagation of a covered + * work results from an entity transaction, each party to that + * transaction who receives a copy of the work also receives whatever + * licenses to the work the party's predecessor in interest had or could + * give under the previous paragraph, plus a right to possession of the + * Corresponding Source of the work from the predecessor in interest, if + * the predecessor has it or can get it with reasonable efforts. + * + * You may not impose any further restrictions on the exercise of the + * rights granted or affirmed under this License. For example, you may + * not impose a license fee, royalty, or other charge for exercise of + * rights granted under this License, and you may not initiate litigation + * (including a cross-claim or counterclaim in a lawsuit) alleging that + * any patent claim is infringed by making, using, selling, offering for + * sale, or importing the Program or any portion of it. + * + * 11. Patents. + * + * A "contributor" is a copyright holder who authorizes use under this + * License of the Program or a work on which the Program is based. The + * work thus licensed is called the contributor's "contributor version". + * + * A contributor's "essential patent claims" are all patent claims + * owned or controlled by the contributor, whether already acquired or + * hereafter acquired, that would be infringed by some manner, permitted + * by this License, of making, using, or selling its contributor version, + * but do not include claims that would be infringed only as a + * consequence of further modification of the contributor version. For + * purposes of this definition, "control" includes the right to grant + * patent sublicenses in a manner consistent with the requirements of + * this License. + * + * Each contributor grants you a non-exclusive, worldwide, royalty-free + * patent license under the contributor's essential patent claims, to + * make, use, sell, offer for sale, import and otherwise run, modify and + * propagate the contents of its contributor version. + * + * In the following three paragraphs, a "patent license" is any express + * agreement or commitment, however denominated, not to enforce a patent + * (such as an express permission to practice a patent or covenant not to + * sue for patent infringement). To "grant" such a patent license to a + * party means to make such an agreement or commitment not to enforce a + * patent against the party. + * + * If you convey a covered work, knowingly relying on a patent license, + * and the Corresponding Source of the work is not available for anyone + * to copy, free of charge and under the terms of this License, through a + * publicly available network server or other readily accessible means, + * then you must either (1) cause the Corresponding Source to be so + * available, or (2) arrange to deprive yourself of the benefit of the + * patent license for this particular work, or (3) arrange, in a manner + * consistent with the requirements of this License, to extend the patent + * license to downstream recipients. "Knowingly relying" means you have + * actual knowledge that, but for the patent license, your conveying the + * covered work in a country, or your recipient's use of the covered work + * in a country, would infringe one or more identifiable patents in that + * country that you have reason to believe are valid. + * + * If, pursuant to or in connection with a single transaction or + * arrangement, you convey, or propagate by procuring conveyance of, a + * covered work, and grant a patent license to some of the parties + * receiving the covered work authorizing them to use, propagate, modify + * or convey a specific copy of the covered work, then the patent license + * you grant is automatically extended to all recipients of the covered + * work and works based on it. + * + * A patent license is "discriminatory" if it does not include within + * the scope of its coverage, prohibits the exercise of, or is + * conditioned on the non-exercise of one or more of the rights that are + * specifically granted under this License. You may not convey a covered + * work if you are a party to an arrangement with a third party that is + * in the business of distributing software, under which you make payment + * to the third party based on the extent of your activity of conveying + * the work, and under which the third party grants, to any of the + * parties who would receive the covered work from you, a discriminatory + * patent license (a) in connection with copies of the covered work + * conveyed by you (or copies made from those copies), or (b) primarily + * for and in connection with specific products or compilations that + * contain the covered work, unless you entered into that arrangement, + * or that patent license was granted, prior to 28 March 2007. + * + * Nothing in this License shall be construed as excluding or limiting + * any implied license or other defenses to infringement that may + * otherwise be available to you under applicable patent law. + * + * 12. No Surrender of Others' Freedom. + * + * If conditions are imposed on you (whether by court order, agreement or + * otherwise) that contradict the conditions of this License, they do not + * excuse you from the conditions of this License. If you cannot convey a + * covered work so as to satisfy simultaneously your obligations under this + * License and any other pertinent obligations, then as a consequence you may + * not convey it at all. For example, if you agree to terms that obligate you + * to collect a royalty for further conveying from those to whom you convey + * the Program, the only way you could satisfy both those terms and this + * License would be to refrain entirely from conveying the Program. + * + * 13. Use with the GNU Affero General Public License. + * + * Notwithstanding any other provision of this License, you have + * permission to link or combine any covered work with a work licensed + * under version 3 of the GNU Affero General Public License into a single + * combined work, and to convey the resulting work. The terms of this + * License will continue to apply to the part which is the covered work, + * but the special requirements of the GNU Affero General Public License, + * section 13, concerning interaction through a network will apply to the + * combination as such. + * + * 14. Revised Versions of this License. + * + * The Free Software Foundation may publish revised and/or new versions of + * the GNU General Public License from time to time. Such new versions will + * be similar in spirit to the present version, but may differ in detail to + * address new problems or concerns. + * + * Each version is given a distinguishing version number. If the + * Program specifies that a certain numbered version of the GNU General + * Public License "or any later version" applies to it, you have the + * option of following the terms and conditions either of that numbered + * version or of any later version published by the Free Software + * Foundation. If the Program does not specify a version number of the + * GNU General Public License, you may choose any version ever published + * by the Free Software Foundation. + * + * If the Program specifies that a proxy can decide which future + * versions of the GNU General Public License can be used, that proxy's + * public statement of acceptance of a version permanently authorizes you + * to choose that version for the Program. + * + * Later license versions may give you additional or different + * permissions. However, no additional obligations are imposed on any + * author or copyright holder as a result of your choosing to follow a + * later version. + * + * 15. Disclaimer of Warranty. + * + * THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + * APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + * HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM + * IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF + * ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + * + * 16. Limitation of Liability. + * + * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS + * THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + * GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + * USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + * DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + * PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + * EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + * + * 17. Interpretation of Sections 15 and 16. + * + * If the disclaimer of warranty and limitation of liability provided + * above cannot be given local legal effect according to their terms, + * reviewing courts shall apply local law that most closely approximates + * an absolute waiver of all civil liability in connection with the + * Program, unless a warranty or assumption of liability accompanies a + * copy of the Program in return for a fee. + * + * END OF TERMS AND CONDITIONS + * + * How to Apply These Terms to Your New Programs + * + * If you develop a new program, and you want it to be of the greatest + * possible use to the public, the best way to achieve this is to make it + * free software which everyone can redistribute and change under these terms. + * + * To do so, attach the following notices to the program. It is safest + * to attach them to the start of each source file to most effectively + * state the exclusion of warranty; and each file should have at least + * the "copyright" line and a pointer to where the full notice is found. + * + * {one line to give the program's name and a brief idea of what it does.} + * Copyright (C) {year} {name of author} + * + * 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 . + * + * Also add information on how to contact you by electronic and paper mail. + * + * If the program does terminal interaction, make it output a short + * notice like this when it starts in an interactive mode: + * + * {project} Copyright (C) {year} {fullname} + * This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + * This is free software, and you are welcome to redistribute it + * under certain conditions; type `show c' for details. + * + * The hypothetical commands `show w' and `show c' should show the appropriate + * parts of the General Public License. Of course, your program's commands + * might be different; for a GUI interface, you would use an "about box". + * + * You should also get your employer (if you work as a programmer) or school, + * if any, to sign a "copyright disclaimer" for the program, if necessary. + * For more information on this, and how to apply and follow the GNU GPL, see + * . + * + * The GNU General Public License does not permit incorporating your program + * into proprietary programs. If your program is a subroutine library, you + * may consider it more useful to permit linking proprietary applications with + * the library. If this is what you want to do, use the GNU Lesser General + * Public License instead of this License. But first, please read + * . + */ + +#ifndef INCLUDED_SATNOGS_LEO_CHANNEL_H +#define INCLUDED_SATNOGS_LEO_CHANNEL_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Channel model that emulates the signal of a LEO satellite. + * It adds the proper doppler shift and in the future will emulate also + * the signal fading based on the sattelite position. + * + * \ingroup satnogs + * + */ + class SATNOGS_API leo_channel : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of satnogs::leo_channel. + * + * To avoid accidental use of raw pointers, satnogs::leo_channel's + * constructor is in a private implementation + * class. satnogs::leo_channel::make is the public interface for + * creating new instances. + */ + static sptr + make (const double freq, const double samp_rate, + const double sat_altitude, + const double sat_inclination, + const size_t pass_duration_sec = 420, + const size_t freq_shifts_per_sec = 100); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_LEO_CHANNEL_H */ + diff --git a/include/satnogs/tcp_rigctl_msg_source.h b/include/satnogs/tcp_rigctl_msg_source.h index 4aaa54f..481a164 100644 --- a/include/satnogs/tcp_rigctl_msg_source.h +++ b/include/satnogs/tcp_rigctl_msg_source.h @@ -44,13 +44,19 @@ namespace gr /** * Rigctl TCP command accepter + * * @param addr the address of the interface to listen at - * @param port the TCP port to listen for TCP connections + * @param port the TCP port to listen or connect + * @param serve_mode If set to yes this block, act as a rigctl server. + * Otherwise as a rigctl client + * @param interval_ms The interval in milliseconds at which the client + * request the frequency from the rigctl * @param mtu the maximum MTU * @return */ static sptr - make (const std::string& addr, uint16_t port, size_t mtu = 1500); + make (const std::string& addr, uint16_t port, bool server_mode, + size_t interval_ms = 1000, size_t mtu = 1500); }; } // namespace satnogs diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f46e70e..46201a5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -29,6 +29,7 @@ list(APPEND satnogs_debug_sources morse_debug_source_impl.cc debug_msg_source_impl.cc debug_msg_source_raw_impl.cc + leo_channel_impl.cc ) list(APPEND satnogs_sources @@ -67,7 +68,8 @@ add_library(gnuradio-satnogs SHARED ${satnogs_sources}) target_link_libraries(gnuradio-satnogs ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) + ${CMAKE_THREAD_LIBS_INIT} + ${NOVA_LIBRARIES}) set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") diff --git a/lib/leo_channel_impl.cc b/lib/leo_channel_impl.cc new file mode 100644 index 0000000..e60f8fb --- /dev/null +++ b/lib/leo_channel_impl.cc @@ -0,0 +1,79 @@ +/* -*- 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 "leo_channel_impl.h" + +namespace gr +{ + namespace satnogs + { + + leo_channel::sptr + leo_channel::make (const double freq, const double samp_rate, + const double sat_altitude, const double sat_inclination, + const size_t pass_duration_sec, + const size_t freq_shifts_per_sec) + { + return gnuradio::get_initial_sptr ( + new leo_channel_impl (freq, freq_shifts_per_sec)); + } + + /* + * The private constructor + */ + leo_channel_impl::leo_channel_impl (const double freq, + const size_t freq_shifts_per_sec) : + gr::sync_block ("leo_channel", + gr::io_signature::make (1, 1, sizeof(gr_complex)), + gr::io_signature::make (1, 1, sizeof(gr_complex))), + d_freq (freq), + d_shifts_per_sec (freq_shifts_per_sec) + { + } + + /* + * Our virtual destructor. + */ + leo_channel_impl::~leo_channel_impl () + { + } + + int + leo_channel_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]; + + // Do <+signal processing+> + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/leo_channel_impl.h b/lib/leo_channel_impl.h new file mode 100644 index 0000000..b19e78b --- /dev/null +++ b/lib/leo_channel_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_LEO_CHANNEL_IMPL_H +#define INCLUDED_SATNOGS_LEO_CHANNEL_IMPL_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + class leo_channel_impl : public leo_channel + { + private: + const double d_freq; + const size_t d_shifts_per_sec; + + public: + leo_channel_impl (const double freq, const size_t freq_shifts_per_sec); + ~leo_channel_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_LEO_CHANNEL_IMPL_H */ + diff --git a/lib/tcp_rigctl_msg_source_impl.cc b/lib/tcp_rigctl_msg_source_impl.cc index 8a10b35..6368741 100644 --- a/lib/tcp_rigctl_msg_source_impl.cc +++ b/lib/tcp_rigctl_msg_source_impl.cc @@ -38,7 +38,6 @@ #include #include - namespace gr { namespace satnogs @@ -46,50 +45,163 @@ namespace gr tcp_rigctl_msg_source::sptr tcp_rigctl_msg_source::make (const std::string& addr, uint16_t port, - size_t mtu) + bool server_mode, size_t interval_ms, + size_t mtu) { return gnuradio::get_initial_sptr ( - new tcp_rigctl_msg_source_impl (addr, port, mtu)); + new tcp_rigctl_msg_source_impl (addr, port, server_mode, interval_ms, + mtu)); } /* * The private constructor */ tcp_rigctl_msg_source_impl::tcp_rigctl_msg_source_impl ( - const std::string& addr, uint16_t port, size_t mtu) : - gr::block ("tcp_rigctl_msg_source", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_iface_addr (addr), - d_port (port), - d_mtu (mtu), - d_running (true) + const std::string& addr, uint16_t port, bool server_mode, + size_t interval_ms, size_t mtu) : + gr::block ("tcp_rigctl_msg_source", + gr::io_signature::make (0, 0, 0), + gr::io_signature::make (0, 0, 0)), + d_ip_addr (addr), + d_port (port), + d_is_server (server_mode), + d_interval_ms(interval_ms), + d_mtu (mtu), + d_running (true) { message_port_register_out (pmt::mp ("freq")); - boost::shared_ptr ( - new boost::thread ( - boost::bind (&tcp_rigctl_msg_source_impl::tcp_msg_accepter, - this))); + if(d_is_server) { + boost::shared_ptr ( + new boost::thread ( + boost::bind (&tcp_rigctl_msg_source_impl::rigctl_server, this))); + } + else{ + boost::shared_ptr ( + new boost::thread ( + boost::bind (&tcp_rigctl_msg_source_impl::rigctl_client, this))); + } } static inline void - send_freq(int sock, uint64_t freq) + send_freq (int sock, uint64_t freq) { static char buf[512]; - snprintf(buf, 512, "%llu\n", freq); - send(sock, buf, strnlen(buf, 512), 0); + snprintf (buf, 512, "%llu\n", freq); + send (sock, buf, strnlen (buf, 512), 0); } static inline void - send_report_code(int sock, int code) + 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); + snprintf (buf, 512, "RPRT %d\n", code); + send (sock, buf, strnlen (buf, 512), 0); + } + + static inline void + request_freq_msg (int sock) + { + static const char *cmd = "f\n"; + send (sock, cmd, strnlen(cmd, 2), 0); + } + + static inline void + send_quit(int sock) + { + static const char *cmd = "q\n"; + send (sock, cmd, strnlen(cmd, 2), 0); } void - tcp_rigctl_msg_source_impl::tcp_msg_accepter () + tcp_rigctl_msg_source_impl::rigctl_client () + { + int sock; + struct sockaddr_in sin; + ssize_t ret; + uint8_t *buf; + double freq = 0.0; + int optval = 1; + struct timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror ("opening UDP socket"); + exit (EXIT_FAILURE); + } + + memset (&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons (d_port); + sin.sin_addr.s_addr = INADDR_ANY; + + if (inet_aton (d_ip_addr.c_str (), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close (sock); + exit (EXIT_FAILURE); + } + + if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0) { + LOG_ERROR("Could not connect at rigctl server %s", d_ip_addr.c_str()); + close (sock); + exit (EXIT_FAILURE); + } + + /* + * Apply the TCP_NODELAY option at the socket for a packet based + * behavior. + */ + if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) + < 0) { + perror ("TCP setsockopt TCP_NODELAY"); + shutdown(sock, SHUT_RDWR); + close(sock); + exit (EXIT_FAILURE); + } + + /* Set a reasonable timeout at the response from the server */ + if (setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) + < 0) { + perror ("TCP setsockopt SO_RCVTIMEO"); + shutdown (sock, SHUT_RDWR); + close (sock); + exit (EXIT_FAILURE); + } + + /* All good until now. Allocate buffer memory and proceed */ + buf = new uint8_t[d_mtu]; + sleep(2); + while (d_running) { + /* Request frequency from rigctl */ + request_freq_msg (sock); + ret = recv (sock, buf, d_mtu, 0); + if (ret > 0) { + freq = get_freq_from_buf (buf); + /* + * If the frequency is different than 0, then the parsed value + * is valid and an appropriate message can be generated + * + * NOTE: Comparison for equality in floats is a bit tricky. + * But here the get_freq_from_buf() will assign a 0.0 explicitly + * if something goes wrong. For this reason it is safe to compare + * the in-equality against 0.0. + */ + if (freq != 0.0 && !std::isnan(freq)) { + message_port_pub (pmt::mp ("freq"), pmt::from_double (freq)); + } + } + boost::this_thread::sleep(boost::posix_time::milliseconds(d_interval_ms)); + } + + send_quit(sock); + shutdown (sock, SHUT_RDWR); + close (sock); + delete[] buf; + exit (EXIT_SUCCESS); + } + + void + tcp_rigctl_msg_source_impl::rigctl_server () { int sock; int listen_sock; @@ -104,8 +216,8 @@ namespace gr int optval = 1; if ((listen_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - perror ("opening UDP socket"); - exit (EXIT_FAILURE); + perror ("opening UDP socket"); + exit (EXIT_FAILURE); } memset (&client_addr, 0, sizeof(struct sockaddr)); @@ -114,84 +226,88 @@ namespace gr sin.sin_port = htons (d_port); sin.sin_addr.s_addr = INADDR_ANY; - if (inet_aton (d_iface_addr.c_str (), &(sin.sin_addr)) == 0) { - LOG_ERROR("Wrong IP address"); - close (listen_sock); - exit (EXIT_FAILURE); + if (inet_aton (d_ip_addr.c_str (), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close (listen_sock); + exit (EXIT_FAILURE); } if (bind (listen_sock, (struct sockaddr *) &sin, - sizeof(struct sockaddr_in)) == -1) { - perror ("TCP bind"); - close (listen_sock); - exit (EXIT_FAILURE); + sizeof(struct sockaddr_in)) == -1) { + perror ("TCP bind"); + close (listen_sock); + exit (EXIT_FAILURE); } if (listen (listen_sock, 1000) == -1) { - perror ("TCP listen"); - close (listen_sock); - exit (EXIT_FAILURE); + perror ("TCP listen"); + close (listen_sock); + exit (EXIT_FAILURE); } /* All good until now. Allocate buffer memory and proceed */ buf = new uint8_t[d_mtu]; while (d_running) { - sock = accept (listen_sock, &client_addr, &client_addr_len); - if (sock <= 0) { - perror ("TCP accept"); - exit (EXIT_FAILURE); - } + sock = accept (listen_sock, &client_addr, &client_addr_len); + if (sock <= 0) { + perror ("TCP accept"); + exit (EXIT_FAILURE); + } - /* 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); - } + /* Apply the TCP_NODELAY option at the accepted socket */ + if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) + < 0) { + perror ("TCP setsockopt"); + shutdown(sock, SHUT_RDWR); + close(sock); + exit (EXIT_FAILURE); + } - while ((ret = recv (sock, buf, d_mtu, 0)) > 0 && d_running) { - switch (buf[0]) - { - case 'F': - freq = get_freq_from_buf (buf + 2); - /* - * If the frequency is different than 0, then the parsed value - * is valid and an appropriate message can be generated - * - * NOTE: Comparison for equality in floats is a bit tricky. - * But here the get_freq_from_buf() will assign a 0.0 explicitly - * if something goes wrong. For this reason it is safe to compare - * the in-equality against 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); - close (sock); + while ((ret = recv (sock, buf, d_mtu, 0)) > 0 && d_running) { + switch (buf[0]) + { + case 'F': + freq = get_freq_from_buf (buf + 2); + /* + * If the frequency is different than 0, then the parsed value + * is valid and an appropriate message can be generated + * + * NOTE: Comparison for equality in floats is a bit tricky. + * But here the get_freq_from_buf() will assign a 0.0 explicitly + * if something goes wrong. For this reason it is safe to compare + * the in-equality against 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); + close (sock); } + shutdown (listen_sock, SHUT_RDWR); close (listen_sock); - delete [] buf; + delete[] buf; exit (EXIT_SUCCESS); } @@ -210,14 +326,14 @@ namespace gr /* Check for various possible errors */ if ((errno == ERANGE && (f == LONG_MAX || f == LONG_MIN)) - || (errno != 0 && f == 0)) { - LOG_WARN("Invalid rigctl command"); - f = 0; + || (errno != 0 && f == 0)) { + LOG_WARN("Invalid rigctl command"); + f = 0; } if ((char *) buf == end) { - LOG_WARN("Invalid rigctl command"); - f = 0; + LOG_WARN("Invalid rigctl command"); + f = 0; } return (double) f; diff --git a/lib/tcp_rigctl_msg_source_impl.h b/lib/tcp_rigctl_msg_source_impl.h index 3c7b50b..63b4e45 100644 --- a/lib/tcp_rigctl_msg_source_impl.h +++ b/lib/tcp_rigctl_msg_source_impl.h @@ -31,20 +31,26 @@ namespace gr class tcp_rigctl_msg_source_impl : public tcp_rigctl_msg_source { private: - const std::string d_iface_addr; + const std::string d_ip_addr; const uint16_t d_port; + const bool d_is_server; + const size_t d_interval_ms; const size_t d_mtu; bool d_running; boost::shared_ptr d_thread; void - tcp_msg_accepter(); + rigctl_server(); + + void + rigctl_client(); double get_freq_from_buf(const uint8_t *buf); public: tcp_rigctl_msg_source_impl (const std::string& addr, uint16_t port, + bool server_mode, size_t interval_ms, size_t mtu); ~tcp_rigctl_msg_source_impl (); }; diff --git a/swig/satnogs_debug_swig.i b/swig/satnogs_debug_swig.i index bfd32f8..d68a11c 100644 --- a/swig/satnogs_debug_swig.i +++ b/swig/satnogs_debug_swig.i @@ -10,6 +10,7 @@ #include "satnogs/morse_debug_source.h" #include "satnogs/debug_msg_source.h" #include "satnogs/debug_msg_source_raw.h" +#include "satnogs/leo_channel.h" %} %include "satnogs/morse_debug_source.h" @@ -21,3 +22,6 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source); %include "satnogs/debug_msg_source_raw.h" GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source_raw); +%include "satnogs/leo_channel.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, leo_channel); + From 94161d7b247467bde3988700dec6bbb91478df31 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Wed, 26 Oct 2016 20:36:07 +0300 Subject: [PATCH 07/26] Change the build system requirements on GNU Radio version and libnova --- CMakeLists.txt | 26 ++++++++++++++------------ README.md | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4603054..f36c25b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,12 +116,22 @@ find_package (Threads REQUIRED) find_package(CppUnit) find_package(Doxygen) +######################################################################## +# Include or not into the module blocks for debugging +######################################################################## +if(NOT INCLUDE_DEBUG_BLOCKS) + set(INCLUDE_DEBUG_BLOCKS ON CACHE BOOL + "Disable blocks that are used for debugging purposes") +endif() + ######################################################################## # Find gr-satnogs external build dependencies ######################################################################## -find_package(Nova) -if(NOT NOVA_FOUND) - message(FATAL_ERROR "libnova required to compile satnogs") +if(${INCLUDE_DEBUG_BLOCKS}) + find_package(Nova) + if(NOT NOVA_FOUND) + message(FATAL_ERROR "libnova required to compile satnogs") + endif() endif() # Search for GNU Radio and its components and versions. Add any @@ -129,7 +139,7 @@ endif() # caps such as FILTER or FFT) and change the version to the minimum # API compatible version required. set(GR_REQUIRED_COMPONENTS RUNTIME) -find_package(Gnuradio "3.7.2" REQUIRED) +find_package(Gnuradio "3.7.7" REQUIRED) if(NOT CPPUNIT_FOUND) message(FATAL_ERROR "CppUnit required to compile satnogs") @@ -144,14 +154,6 @@ else(DOXYGEN_FOUND) option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) endif(DOXYGEN_FOUND) -######################################################################## -# Include or not into the module blocks for debugging -######################################################################## -if(NOT INCLUDE_DEBUG_BLOCKS) - set(INCLUDE_DEBUG_BLOCKS ON CACHE BOOL - "Disable blocks that are used for debugging purposes") -endif() - ######################################################################## # Setup the include and linker paths ######################################################################## diff --git a/README.md b/README.md index 438af03..ba1f62e 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,14 @@ for decoding signals from various scientific and academic sattelites. ## Install ### Requirements -1. GNU Radio ( > 3.7.2 ) -2. CMake ( > 3.1) -3. G++ (with C++11 support) -4. VOLK -5. git -6. gr-osmocom (optional, for using the flowgraphs) +* GNU Radio ( > 3.7.2 ) +* CMake ( > 3.1) +* G++ (with C++11 support) +* VOLK +* git +*** Optional *** +* gr-osmocom (for using the flowgraphs with real SDR hardware) +* libnova (for building the debug blocks) ### Installation @@ -32,9 +34,9 @@ E.g: `cmake -DCMAKE_INSTALL_PREFIX=/usr ..` -Also, by default the build system disables a set of blocks used for debugging +Also, by default the build system enables a set of blocks used for debugging during the development. The enable/disable switch is controled through the -`INCLUDE_DEBUG_BLOCKS` boolean variable. If for example, you want to enable the +`INCLUDE_DEBUG_BLOCKS` boolean variable. If for example, you want to disable the debugging blocks, the **CMake** command would be: `cmake -DINCLUDE_DEBUG_BLOCKS=OFF ..` From eff240e8916e8195998c457cfe1d3262a379488b Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Mon, 31 Oct 2016 21:10:18 +0200 Subject: [PATCH 08/26] Update the flowgraphs affected by the rigctl block changes --- apps/flowgraphs/generic_iq_receiver.grc | 16 ++++++++++++---- apps/flowgraphs/satnogs_fm_demod.py | 2 +- apps/flowgraphs/satnogs_generic_iq_receiver.py | 10 +++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/flowgraphs/generic_iq_receiver.grc b/apps/flowgraphs/generic_iq_receiver.grc index ed25c2a..9a7f388 100644 --- a/apps/flowgraphs/generic_iq_receiver.grc +++ b/apps/flowgraphs/generic_iq_receiver.grc @@ -2569,10 +2569,6 @@ we shift the LO a little further addr "127.0.0.1" - - port - rigctl_port - mtu 1500 @@ -2585,6 +2581,18 @@ we shift the LO a little further minoutbuf 0 + + mode + False + + + port + rigctl_port + + + interval + 1000 + analog_sig_source_x_0 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index 42d51dc..bf9cd4e 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Fri Oct 21 22:22:13 2016 +# Generated: Mon Oct 31 21:08:24 2016 ################################################## from gnuradio import analog diff --git a/apps/flowgraphs/satnogs_generic_iq_receiver.py b/apps/flowgraphs/satnogs_generic_iq_receiver.py index a9a25e0..c7d1da4 100755 --- a/apps/flowgraphs/satnogs_generic_iq_receiver.py +++ b/apps/flowgraphs/satnogs_generic_iq_receiver.py @@ -5,7 +5,7 @@ # Title: Generic IQ samples receiver # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Oct 17 19:32:33 2016 +# Generated: Mon Oct 31 21:08:00 2016 ################################################## from gnuradio import blocks @@ -22,7 +22,7 @@ import time class satnogs_generic_iq_receiver(gr.top_block): - def __init__(self, doppler_correction_per_sec=1000, file_path="test.wav", lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device="usrpb200"): + def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200'): gr.top_block.__init__(self, "Generic IQ samples receiver") ################################################## @@ -51,7 +51,7 @@ class satnogs_generic_iq_receiver(gr.top_block): ################################################## # Blocks ################################################## - self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, 1500) + self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) self.osmosdr_source_0.set_sample_rate(samp_rate_rx) @@ -180,7 +180,7 @@ def argument_parser(): "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000, help="Set doppler_correction_per_sec [default=%default]") parser.add_option( - "", "--file-path", dest="file_path", type="string", default="test.wav", + "", "--file-path", dest="file_path", type="string", default='test.wav', help="Set file_path [default=%default]") parser.add_option( "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), @@ -192,7 +192,7 @@ def argument_parser(): "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6), help="Set rx_freq [default=%default]") parser.add_option( - "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default="usrpb200", + "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200', help="Set rx_sdr_device [default=%default]") return parser From 31fdde553a15b062906dbaa5d8b529229f267205 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Mon, 7 Nov 2016 19:53:57 +0200 Subject: [PATCH 09/26] Fix the DC issue at the generic receivers (#40) Until proper debugging, the receivers are now using the coarse doppler correction mechanism. --- apps/flowgraphs/fm_demod.grc | 20 ++++++-------- apps/flowgraphs/generic_iq_receiver.grc | 26 ++++++++----------- apps/flowgraphs/satnogs_fm_demod.py | 13 +++++----- .../flowgraphs/satnogs_generic_iq_receiver.py | 13 +++++----- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index 08a8194..e6d9748 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -763,7 +763,7 @@ we shift the LO a little further dc_offset_mode0 - 0 + 2 corr0 @@ -2642,7 +2642,7 @@ we shift the LO a little further - satnogs_doppler_correction_cc + satnogs_coarse_doppler_correction_cc alias @@ -2655,17 +2655,13 @@ we shift the LO a little further affinity - - corrections_per_sec - doppler_correction_per_sec - _enabled - 1 + True _coordinate - (304, 256) + (272, 280) _rotation @@ -2673,7 +2669,7 @@ we shift the LO a little further id - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 maxoutbuf @@ -2789,7 +2785,7 @@ we shift the LO a little further osmosdr_source_0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 0 0 @@ -2800,14 +2796,14 @@ we shift the LO a little further 0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 freq_xlating_fir_filter_xxx_0 0 0 satnogs_tcp_rigctl_msg_source_0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 freq freq diff --git a/apps/flowgraphs/generic_iq_receiver.grc b/apps/flowgraphs/generic_iq_receiver.grc index 9a7f388..b0b91e0 100644 --- a/apps/flowgraphs/generic_iq_receiver.grc +++ b/apps/flowgraphs/generic_iq_receiver.grc @@ -386,7 +386,7 @@ TX sampling rate _coordinate - (784, 284) + (1136, 284) _rotation @@ -574,7 +574,7 @@ TX sampling rate _coordinate - (520, 280) + (896, 280) _rotation @@ -669,7 +669,7 @@ we shift the LO a little further dc_offset_mode0 - 0 + 2 corr0 @@ -2064,7 +2064,7 @@ we shift the LO a little further average - 1.0 + 0.2 axislabels @@ -2485,7 +2485,7 @@ we shift the LO a little further - satnogs_doppler_correction_cc + satnogs_coarse_doppler_correction_cc alias @@ -2498,17 +2498,13 @@ we shift the LO a little further affinity - - corrections_per_sec - doppler_correction_per_sec - _enabled - 1 + True _coordinate - (304, 256) + (568, 288) _rotation @@ -2516,7 +2512,7 @@ we shift the LO a little further id - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 maxoutbuf @@ -2620,19 +2616,19 @@ we shift the LO a little further osmosdr_source_0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 0 0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 freq_xlating_fir_filter_xxx_0 0 0 satnogs_tcp_rigctl_msg_source_0 - satnogs_doppler_correction_cc_0 + satnogs_coarse_doppler_correction_cc_0 freq freq diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index bf9cd4e..c78df64 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Oct 31 21:08:24 2016 +# Generated: Mon Nov 7 19:50:22 2016 ################################################## from gnuradio import analog @@ -54,7 +54,7 @@ class satnogs_fm_demod(gr.top_block): # Blocks ################################################## self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) - self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) + self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation), taps=(firdes.low_pass_2(32, 32, 0.8, 0.1, 100)), @@ -65,7 +65,7 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0.set_sample_rate(samp_rate_rx) self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) self.osmosdr_source_0.set_freq_corr(0, 0) - self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(2, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0) @@ -85,13 +85,13 @@ class satnogs_fm_demod(gr.top_block): ################################################## # Connections ################################################## - self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_doppler_correction_cc_0, 'freq')) + self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) self.connect((self.analog_wfm_rcv_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.analog_wfm_rcv_0, 0)) - self.connect((self.osmosdr_source_0, 0), (self.satnogs_doppler_correction_cc_0, 0)) + self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_multiply_const_vxx_0, 0)) - self.connect((self.satnogs_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) def get_doppler_correction_per_sec(self): return self.doppler_correction_per_sec @@ -125,6 +125,7 @@ class satnogs_fm_demod(gr.top_block): def set_rx_freq(self, rx_freq): self.rx_freq = rx_freq + self.satnogs_coarse_doppler_correction_cc_0.set_new_freq_locked(self.rx_freq) self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) def get_rx_sdr_device(self): diff --git a/apps/flowgraphs/satnogs_generic_iq_receiver.py b/apps/flowgraphs/satnogs_generic_iq_receiver.py index c7d1da4..5f1b296 100755 --- a/apps/flowgraphs/satnogs_generic_iq_receiver.py +++ b/apps/flowgraphs/satnogs_generic_iq_receiver.py @@ -5,7 +5,7 @@ # Title: Generic IQ samples receiver # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Oct 31 21:08:00 2016 +# Generated: Mon Nov 7 19:49:15 2016 ################################################## from gnuradio import blocks @@ -52,12 +52,12 @@ class satnogs_generic_iq_receiver(gr.top_block): # Blocks ################################################## self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) - self.satnogs_doppler_correction_cc_0 = satnogs.doppler_correction_cc(rx_freq, samp_rate_rx, doppler_correction_per_sec) + self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) self.osmosdr_source_0.set_sample_rate(samp_rate_rx) self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) self.osmosdr_source_0.set_freq_corr(0, 0) - self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(2, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0) @@ -73,10 +73,10 @@ class satnogs_generic_iq_receiver(gr.top_block): ################################################## # Connections ################################################## - self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_doppler_correction_cc_0, 'freq')) + self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blocks_file_sink_0, 0)) - self.connect((self.osmosdr_source_0, 0), (self.satnogs_doppler_correction_cc_0, 0)) - self.connect((self.satnogs_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) + self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) def get_doppler_correction_per_sec(self): return self.doppler_correction_per_sec @@ -110,6 +110,7 @@ class satnogs_generic_iq_receiver(gr.top_block): def set_rx_freq(self, rx_freq): self.rx_freq = rx_freq + self.satnogs_coarse_doppler_correction_cc_0.set_new_freq_locked(self.rx_freq) self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) def get_rx_sdr_device(self): From 0e0d032a199ce520e94d72d6e963392f57cd4e19 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Sun, 13 Nov 2016 11:05:36 -0500 Subject: [PATCH 10/26] Fix gain settings for hackrf (#41) Adjusting to the 'sweet spot' for hackrf in the gr-satnogs script --- python/hw_settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/hw_settings.py b/python/hw_settings.py index 730b463..570b875 100644 --- a/python/hw_settings.py +++ b/python/hw_settings.py @@ -29,8 +29,8 @@ hw_tx_settings = {'usrpb200' : {'rf_gain' : 60.0, 'if_gain' : 0.0, 'usrp2' : {'rf_gain' : 20.0, 'samp_rate' : 2e6, 'bb_gain' : 0.0, 'samp_rate' : 2e6, 'antenna' : 'TX/RX', 'dev_arg': 'uhd'}, - 'hackrf' : {'rf_gain' : 20.0, 'if_gain' : 8.0, - 'bb_gain' : 5.0, 'samp_rate' : 2e6, + 'hackrf' : {'rf_gain' : 0.0, 'if_gain' : 16.0, + 'bb_gain' : 20.0, 'samp_rate' : 2e6, 'antenna' : '', 'dev_arg': 'hackrf'} } hw_rx_settings = {'usrpb200' : {'rf_gain' : 20.0, 'if_gain' : 0.0, @@ -42,8 +42,8 @@ hw_rx_settings = {'usrpb200' : {'rf_gain' : 20.0, 'if_gain' : 0.0, 'airspy' : {'rf_gain' : 16.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 2.5e6, 'antenna' : '', 'dev_arg': 'airspy'}, - 'hackrf' : {'rf_gain' : 20.0, 'if_gain' : 8.0, - 'bb_gain' : 5.0, 'samp_rate' : 2e6, + 'hackrf' : {'rf_gain' : 0.0, 'if_gain' : 16.0, + 'bb_gain' : 20.0, 'samp_rate' : 2e6, 'antenna' : '', 'dev_arg': 'hackrf'}, 'rtlsdr' : {'rf_gain' : 32.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 1.024e6, From 32b853134a47904f37586c7cb097c1cdb5e6da80 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Tue, 22 Nov 2016 11:49:42 +0200 Subject: [PATCH 11/26] Fix Doppler shift direction (#43) --- lib/coarse_doppler_correction_cc_impl.cc | 3 ++- lib/doppler_correction_cc_impl.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/coarse_doppler_correction_cc_impl.cc b/lib/coarse_doppler_correction_cc_impl.cc index 025fbc9..345df41 100644 --- a/lib/coarse_doppler_correction_cc_impl.cc +++ b/lib/coarse_doppler_correction_cc_impl.cc @@ -25,6 +25,7 @@ #include #include "coarse_doppler_correction_cc_impl.h" #include +#include namespace gr { @@ -86,7 +87,7 @@ namespace gr boost::mutex::scoped_lock lock (d_mutex); double new_freq; new_freq = pmt::to_double (msg); - d_freq_diff = d_target_freq - new_freq; + d_freq_diff = new_freq - d_target_freq; d_nco.set_freq ((2 * M_PI * (-d_freq_diff)) / d_samp_rate); } diff --git a/lib/doppler_correction_cc_impl.cc b/lib/doppler_correction_cc_impl.cc index 2d1525b..36aebf9 100644 --- a/lib/doppler_correction_cc_impl.cc +++ b/lib/doppler_correction_cc_impl.cc @@ -102,7 +102,7 @@ namespace gr boost::mutex::scoped_lock lock (d_mutex); double new_freq; new_freq = pmt::to_double (msg); - d_freq_diff = d_target_freq - new_freq; + d_freq_diff = new_freq - d_target_freq; if (!d_have_est) { d_freq_est_num++; d_doppler_freqs.push_back ( From d662760adf728f0fbeb16f397e684ffbf1159979 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Sun, 4 Dec 2016 00:40:55 +0200 Subject: [PATCH 12/26] Redesign of the OOT module block structure --- CMakeLists.txt | 6 +-- apps/CMakeLists.txt | 3 +- apps/flowgraphs/satellites/CMakeLists.txt | 26 +++++++++++++ .../{ => satellites}/upsat_afsk_receiver.grc | 0 .../upsat_afsk_transmitter.grc | 0 .../{ => satellites}/upsat_fsk_receiver.grc | 0 .../upsat_fsk_transmitter.grc | 0 .../upsat_transceiver_cli.grc | 0 .../{ => satellites}/upsat_transceiver_cli.py | 0 .../{ => satellites}/upsat_transceiver_qt.grc | 0 grc/CMakeLists.txt | 19 ++++------ grc/satellites/CMakeLists.txt | 21 ++++++++++ grc/satellites/upsat/CMakeLists.txt | 30 +++++++++++++++ .../upsat}/satnogs_qb50_deframer.xml | 1 - .../satnogs_upsat_fsk_frame_acquisition.xml | 1 - .../satnogs_upsat_fsk_frame_encoder.xml | 1 - .../upsat}/satnogs_upsat_transmitter.xml | 1 - grc/satnogs_ax25_decoder_bm.xml | 1 - grc/satnogs_ax25_encoder_mb.xml | 1 - grc/satnogs_block_tree.xml | 25 ++++++++++++ grc/satnogs_coarse_doppler_correction_cc.xml | 1 - grc/satnogs_cw_matched_filter_ff.xml | 1 - grc/satnogs_cw_to_symbol.xml | 1 - grc/satnogs_debug_msg_source.xml | 2 +- grc/satnogs_debug_msg_source_raw.xml | 2 +- grc/satnogs_doppler_correction_cc.xml | 1 - grc/satnogs_frame_encoder.xml | 38 ------------------- grc/satnogs_leo_channel.xml | 4 +- grc/satnogs_morse_debug_source.xml | 2 +- grc/satnogs_morse_decoder.xml | 1 - grc/satnogs_multi_format_msg_sink.xml | 1 - grc/satnogs_sine_matched_filter_ff.xml | 1 - grc/satnogs_tcp_rigctl_msg_source.xml | 1 - grc/satnogs_udp_msg_sink.xml | 1 - grc/satnogs_udp_msg_source.xml | 1 - grc/satnogs_whitening.xml | 38 ------------------- 36 files changed, 119 insertions(+), 113 deletions(-) create mode 100644 apps/flowgraphs/satellites/CMakeLists.txt rename apps/flowgraphs/{ => satellites}/upsat_afsk_receiver.grc (100%) rename apps/flowgraphs/{ => satellites}/upsat_afsk_transmitter.grc (100%) rename apps/flowgraphs/{ => satellites}/upsat_fsk_receiver.grc (100%) rename apps/flowgraphs/{ => satellites}/upsat_fsk_transmitter.grc (100%) rename apps/flowgraphs/{ => satellites}/upsat_transceiver_cli.grc (100%) rename apps/flowgraphs/{ => satellites}/upsat_transceiver_cli.py (100%) rename apps/flowgraphs/{ => satellites}/upsat_transceiver_qt.grc (100%) create mode 100644 grc/satellites/CMakeLists.txt create mode 100644 grc/satellites/upsat/CMakeLists.txt rename grc/{ => satellites/upsat}/satnogs_qb50_deframer.xml (94%) rename grc/{ => satellites/upsat}/satnogs_upsat_fsk_frame_acquisition.xml (97%) rename grc/{ => satellites/upsat}/satnogs_upsat_fsk_frame_encoder.xml (98%) rename grc/{ => satellites/upsat}/satnogs_upsat_transmitter.xml (98%) create mode 100644 grc/satnogs_block_tree.xml delete mode 100644 grc/satnogs_frame_encoder.xml delete mode 100644 grc/satnogs_whitening.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index f36c25b..d08bd10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,10 +119,8 @@ find_package(Doxygen) ######################################################################## # Include or not into the module blocks for debugging ######################################################################## -if(NOT INCLUDE_DEBUG_BLOCKS) - set(INCLUDE_DEBUG_BLOCKS ON CACHE BOOL - "Disable blocks that are used for debugging purposes") -endif() +option(INCLUDE_DEBUG_BLOCKS "Enable/Disable blocks that are used for debugging purposes" ON) + ######################################################################## # Find gr-satnogs external build dependencies diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 318d7ea..65be159 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -19,9 +19,10 @@ include(GrPython) +add_subdirectory(flowgraphs/satellites) + GR_PYTHON_INSTALL( PROGRAMS - flowgraphs/upsat_transceiver_cli.py flowgraphs/satnogs_fm_demod.py flowgraphs/satnogs_generic_iq_receiver.py DESTINATION bin diff --git a/apps/flowgraphs/satellites/CMakeLists.txt b/apps/flowgraphs/satellites/CMakeLists.txt new file mode 100644 index 0000000..41d7d3c --- /dev/null +++ b/apps/flowgraphs/satellites/CMakeLists.txt @@ -0,0 +1,26 @@ +# 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. + +include(GrPython) + +GR_PYTHON_INSTALL( + PROGRAMS + upsat_transceiver_cli.py + DESTINATION bin +) \ No newline at end of file diff --git a/apps/flowgraphs/upsat_afsk_receiver.grc b/apps/flowgraphs/satellites/upsat_afsk_receiver.grc similarity index 100% rename from apps/flowgraphs/upsat_afsk_receiver.grc rename to apps/flowgraphs/satellites/upsat_afsk_receiver.grc diff --git a/apps/flowgraphs/upsat_afsk_transmitter.grc b/apps/flowgraphs/satellites/upsat_afsk_transmitter.grc similarity index 100% rename from apps/flowgraphs/upsat_afsk_transmitter.grc rename to apps/flowgraphs/satellites/upsat_afsk_transmitter.grc diff --git a/apps/flowgraphs/upsat_fsk_receiver.grc b/apps/flowgraphs/satellites/upsat_fsk_receiver.grc similarity index 100% rename from apps/flowgraphs/upsat_fsk_receiver.grc rename to apps/flowgraphs/satellites/upsat_fsk_receiver.grc diff --git a/apps/flowgraphs/upsat_fsk_transmitter.grc b/apps/flowgraphs/satellites/upsat_fsk_transmitter.grc similarity index 100% rename from apps/flowgraphs/upsat_fsk_transmitter.grc rename to apps/flowgraphs/satellites/upsat_fsk_transmitter.grc diff --git a/apps/flowgraphs/upsat_transceiver_cli.grc b/apps/flowgraphs/satellites/upsat_transceiver_cli.grc similarity index 100% rename from apps/flowgraphs/upsat_transceiver_cli.grc rename to apps/flowgraphs/satellites/upsat_transceiver_cli.grc diff --git a/apps/flowgraphs/upsat_transceiver_cli.py b/apps/flowgraphs/satellites/upsat_transceiver_cli.py similarity index 100% rename from apps/flowgraphs/upsat_transceiver_cli.py rename to apps/flowgraphs/satellites/upsat_transceiver_cli.py diff --git a/apps/flowgraphs/upsat_transceiver_qt.grc b/apps/flowgraphs/satellites/upsat_transceiver_qt.grc similarity index 100% rename from apps/flowgraphs/upsat_transceiver_qt.grc rename to apps/flowgraphs/satellites/upsat_transceiver_qt.grc diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index a8f0ba5..90cdd05 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -15,16 +15,19 @@ # 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. +# Boston, MA + +add_subdirectory(satellites) list(APPEND debug_blocks - satnogs_morse_debug_source.xml - satnogs_debug_msg_source.xml - satnogs_debug_msg_source_raw.xml - satnogs_leo_channel.xml + satnogs_morse_debug_source.xml + satnogs_debug_msg_source.xml + satnogs_debug_msg_source_raw.xml + satnogs_leo_channel.xml ) list(APPEND enabled_blocks + satnogs_block_tree.xml satnogs_cw_matched_filter_ff.xml satnogs_morse_decoder.xml satnogs_multi_format_msg_sink.xml @@ -32,17 +35,11 @@ list(APPEND enabled_blocks satnogs_sine_matched_filter_ff.xml satnogs_udp_msg_source.xml satnogs_tcp_rigctl_msg_source.xml - satnogs_frame_encoder.xml satnogs_doppler_correction_cc.xml - satnogs_upsat_fsk_frame_acquisition.xml - satnogs_upsat_fsk_frame_encoder.xml - satnogs_whitening.xml satnogs_udp_msg_sink.xml - satnogs_upsat_transmitter.xml satnogs_coarse_doppler_correction_cc.xml satnogs_ax25_encoder_mb.xml satnogs_ax25_decoder_bm.xml - satnogs_qb50_deframer.xml ) if(${INCLUDE_DEBUG_BLOCKS}) diff --git a/grc/satellites/CMakeLists.txt b/grc/satellites/CMakeLists.txt new file mode 100644 index 0000000..69d7f61 --- /dev/null +++ b/grc/satellites/CMakeLists.txt @@ -0,0 +1,21 @@ +# 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. + + +add_subdirectory(upsat) diff --git a/grc/satellites/upsat/CMakeLists.txt b/grc/satellites/upsat/CMakeLists.txt new file mode 100644 index 0000000..006546f --- /dev/null +++ b/grc/satellites/upsat/CMakeLists.txt @@ -0,0 +1,30 @@ +# 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. + +list(APPEND blocks + satnogs_qb50_deframer.xml + satnogs_upsat_fsk_frame_acquisition.xml + satnogs_upsat_fsk_frame_encoder.xml + satnogs_upsat_transmitter.xml +) + +install(FILES + ${blocks} + DESTINATION share/gnuradio/grc/blocks +) \ No newline at end of file diff --git a/grc/satnogs_qb50_deframer.xml b/grc/satellites/upsat/satnogs_qb50_deframer.xml similarity index 94% rename from grc/satnogs_qb50_deframer.xml rename to grc/satellites/upsat/satnogs_qb50_deframer.xml index fba319a..09b4544 100644 --- a/grc/satnogs_qb50_deframer.xml +++ b/grc/satellites/upsat/satnogs_qb50_deframer.xml @@ -2,7 +2,6 @@ QB50 AX.25 Deframer satnogs_qb50_deframer - satnogs import satnogs satnogs.qb50_deframer($wod_ssid) diff --git a/grc/satnogs_upsat_fsk_frame_acquisition.xml b/grc/satellites/upsat/satnogs_upsat_fsk_frame_acquisition.xml similarity index 97% rename from grc/satnogs_upsat_fsk_frame_acquisition.xml rename to grc/satellites/upsat/satnogs_upsat_fsk_frame_acquisition.xml index 9e4e83b..72c3483 100644 --- a/grc/satnogs_upsat_fsk_frame_acquisition.xml +++ b/grc/satellites/upsat/satnogs_upsat_fsk_frame_acquisition.xml @@ -2,7 +2,6 @@ UPSAT FSK Frame Acquisition satnogs_upsat_fsk_frame_acquisition - satnogs import satnogs satnogs.upsat_fsk_frame_acquisition($preamble, $sync_word, $whitening, $manchester, $check_crc, $ax_25) diff --git a/grc/satnogs_upsat_fsk_frame_encoder.xml b/grc/satellites/upsat/satnogs_upsat_fsk_frame_encoder.xml similarity index 98% rename from grc/satnogs_upsat_fsk_frame_encoder.xml rename to grc/satellites/upsat/satnogs_upsat_fsk_frame_encoder.xml index 1fb7b5d..bebc82f 100644 --- a/grc/satnogs_upsat_fsk_frame_encoder.xml +++ b/grc/satellites/upsat/satnogs_upsat_fsk_frame_encoder.xml @@ -2,7 +2,6 @@ UPSAT FSK Frame Encoder satnogs_upsat_fsk_frame_encoder - satnogs import satnogs 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) diff --git a/grc/satnogs_upsat_transmitter.xml b/grc/satellites/upsat/satnogs_upsat_transmitter.xml similarity index 98% rename from grc/satnogs_upsat_transmitter.xml rename to grc/satellites/upsat/satnogs_upsat_transmitter.xml index 30fed3e..822a7ac 100644 --- a/grc/satnogs_upsat_transmitter.xml +++ b/grc/satellites/upsat/satnogs_upsat_transmitter.xml @@ -1,7 +1,6 @@ Satnogs UPSat Transmitter satnogs_upsat_transmitter - satnogs import satnogs satnogs.satnogs_upsat_transmitter(frame_preamble=$frame_preamble, diff --git a/grc/satnogs_ax25_decoder_bm.xml b/grc/satnogs_ax25_decoder_bm.xml index 423fe06..272fc1c 100644 --- a/grc/satnogs_ax25_decoder_bm.xml +++ b/grc/satnogs_ax25_decoder_bm.xml @@ -2,7 +2,6 @@ AX.25 Decoder satnogs_ax25_decoder_bm - satnogs import satnogs satnogs.ax25_decoder_bm($addr, $ssid, $promisc, $descrambling, $max_frame_len, $n_sync_flags) diff --git a/grc/satnogs_ax25_encoder_mb.xml b/grc/satnogs_ax25_encoder_mb.xml index c49e501..9f04f5b 100644 --- a/grc/satnogs_ax25_encoder_mb.xml +++ b/grc/satnogs_ax25_encoder_mb.xml @@ -2,7 +2,6 @@ AX.25 Encoder satnogs_ax25_encoder_mb - satnogs import satnogs satnogs.ax25_encoder_mb($dest_addr, $dest_ssid, $src_addr, $src_ssid, $preamble_len, $postamble_len, $scramble) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml new file mode 100644 index 0000000..345437f --- /dev/null +++ b/grc/satnogs_block_tree.xml @@ -0,0 +1,25 @@ + + [SatNOGS] + + Satellites + + UPSat + satnogs_upsat_fsk_frame_acquisition + satnogs_upsat_fsk_frame_encoder + satnogs_upsat_transmitter + satnogs_qb50_deframer + + + satnogs_cw_matched_filter_ff + satnogs_morse_decoder + satnogs_multi_format_msg_sink + satnogs_cw_to_symbol + satnogs_sine_matched_filter_ff + satnogs_udp_msg_source + satnogs_tcp_rigctl_msg_source + satnogs_doppler_correction_cc + satnogs_udp_msg_sink + satnogs_coarse_doppler_correction_cc + satnogs_ax25_encoder_mb + satnogs_ax25_decoder_bm + \ No newline at end of file diff --git a/grc/satnogs_coarse_doppler_correction_cc.xml b/grc/satnogs_coarse_doppler_correction_cc.xml index 167ec28..99dbcf3 100644 --- a/grc/satnogs_coarse_doppler_correction_cc.xml +++ b/grc/satnogs_coarse_doppler_correction_cc.xml @@ -2,7 +2,6 @@ Coarse Doppler Correction satnogs_coarse_doppler_correction_cc - satnogs import satnogs satnogs.coarse_doppler_correction_cc($target_freq, $sampling_rate) set_new_freq_locked($target_freq) diff --git a/grc/satnogs_cw_matched_filter_ff.xml b/grc/satnogs_cw_matched_filter_ff.xml index 67abe2f..411f183 100644 --- a/grc/satnogs_cw_matched_filter_ff.xml +++ b/grc/satnogs_cw_matched_filter_ff.xml @@ -2,7 +2,6 @@ CW Matched Filter satnogs_cw_matched_filter_ff - satnogs import satnogs satnogs.cw_matched_filter_ff($sampling_rate, $carrier_freq, $wpm, $energy) set_new_freq_locked($carrier_freq) diff --git a/grc/satnogs_cw_to_symbol.xml b/grc/satnogs_cw_to_symbol.xml index a93f997..d106d87 100644 --- a/grc/satnogs_cw_to_symbol.xml +++ b/grc/satnogs_cw_to_symbol.xml @@ -2,7 +2,6 @@ CW to Symbols satnogs_cw_to_symbol - satnogs import satnogs satnogs.cw_to_symbol($sampling_rate, $threshold, $conf_level, $wpm, $auto_config) set_act_threshold($threshold) diff --git a/grc/satnogs_debug_msg_source.xml b/grc/satnogs_debug_msg_source.xml index 7b706e0..1980ac5 100644 --- a/grc/satnogs_debug_msg_source.xml +++ b/grc/satnogs_debug_msg_source.xml @@ -2,7 +2,7 @@ Debug Message Source satnogs_debug_msg_source - satnogs + [SatNOGS]/Debug import satnogs satnogs.debug_msg_source($msg, $delay, $repeat) diff --git a/grc/satnogs_debug_msg_source_raw.xml b/grc/satnogs_debug_msg_source_raw.xml index 3ea8ccd..d668df3 100644 --- a/grc/satnogs_debug_msg_source_raw.xml +++ b/grc/satnogs_debug_msg_source_raw.xml @@ -2,7 +2,7 @@ Debug Message Source Raw satnogs_debug_msg_source_raw - satnogs + [SatNOGS]/Debug import satnogs satnogs.debug_msg_source_raw($msg, $delay, $repeat) diff --git a/grc/satnogs_doppler_correction_cc.xml b/grc/satnogs_doppler_correction_cc.xml index 63840f8..1649d3e 100644 --- a/grc/satnogs_doppler_correction_cc.xml +++ b/grc/satnogs_doppler_correction_cc.xml @@ -2,7 +2,6 @@ Doppler Correction satnogs_doppler_correction_cc - satnogs import satnogs satnogs.doppler_correction_cc($target_freq, $sampling_rate, $corrections_per_sec) diff --git a/grc/satnogs_frame_encoder.xml b/grc/satnogs_frame_encoder.xml deleted file mode 100644 index f628dd9..0000000 --- a/grc/satnogs_frame_encoder.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 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/grc/satnogs_leo_channel.xml b/grc/satnogs_leo_channel.xml index 7df7ae5..8cabddd 100644 --- a/grc/satnogs_leo_channel.xml +++ b/grc/satnogs_leo_channel.xml @@ -1,8 +1,8 @@ - leo_channel + LEO Channel satnogs_leo_channel - [satnogs] + [SatNOGS]/Debug import satnogs satnogs.leo_channel($freq, $freq_shifts_per_sec) - - ... - ... - ... - - - - - in - - - - - - out - - - From 5a3c5b536dbc69b09fe553f74f9d770bb2373823 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Mon, 9 Jan 2017 08:42:02 -0500 Subject: [PATCH 13/26] increase canvas for fm_demod in grc (#47) No functional changes here - just increased the canvas size within gnuradio-companion and moved things around to make it easier to read and work with. --- apps/flowgraphs/fm_demod.grc | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index e6d9748..fd5f6f3 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -10,7 +10,7 @@ window_size - + 3000,3000 category @@ -93,7 +93,7 @@ _coordinate - (568, 508) + (1864, 12) _rotation @@ -122,7 +122,7 @@ SDR received samples _coordinate - (336, 612) + (1296, 12) _rotation @@ -149,7 +149,7 @@ SDR received samples _coordinate - (568, 580) + (2072, 12) _rotation @@ -178,7 +178,7 @@ SDR received samples _coordinate - (192, 612) + (1088, 12) _rotation @@ -205,7 +205,7 @@ SDR received samples _coordinate - (432, 476) + (1680, 12) _rotation @@ -233,7 +233,7 @@ TX sampling rate _coordinate - (192, 484) + (1512, 12) _rotation @@ -268,7 +268,7 @@ TX sampling rate _coordinate - (560, 648) + (32, 788) _rotation @@ -323,7 +323,7 @@ TX sampling rate _coordinate - (312, 24) + (320, 12) _rotation @@ -382,7 +382,7 @@ TX sampling rate _coordinate - (736, 292) + (1176, 476) _rotation @@ -429,11 +429,11 @@ TX sampling rate _coordinate - (976, 444) + (1808, 484) _rotation - 180 + 0 id @@ -476,7 +476,7 @@ TX sampling rate _coordinate - (568, 64) + (568, 140) _rotation @@ -535,11 +535,11 @@ TX sampling rate _coordinate - (800, 428) + (2056, 464) _rotation - 180 + 0 id @@ -570,7 +570,7 @@ TX sampling rate _coordinate - (64, 860) + (1904, 192) _rotation @@ -613,7 +613,7 @@ TX sampling rate _coordinate - (64, 620) + (1272, 192) _rotation @@ -668,7 +668,7 @@ TX sampling rate _coordinate - (520, 280) + (808, 452) _rotation @@ -716,7 +716,7 @@ we shift the LO a little further _coordinate - (328, 476) + (1736, 192) _rotation @@ -2047,7 +2047,7 @@ we shift the LO a little further _coordinate - (24, 264) + (16, 368) _rotation @@ -2170,7 +2170,7 @@ we shift the LO a little further _coordinate - (944, 288) + (1456, 452) _rotation @@ -2261,7 +2261,7 @@ we shift the LO a little further _coordinate - (792, 28) + (728, 120) gui_hint @@ -2528,7 +2528,7 @@ we shift the LO a little further _coordinate - (64, 780) + (1576, 192) _rotation @@ -2571,7 +2571,7 @@ we shift the LO a little further _coordinate - (64, 700) + (1432, 192) _rotation @@ -2614,7 +2614,7 @@ we shift the LO a little further _coordinate - (64, 484) + (1080, 192) _rotation @@ -2661,7 +2661,7 @@ we shift the LO a little further _coordinate - (272, 280) + (464, 460) _rotation @@ -2708,7 +2708,7 @@ we shift the LO a little further _coordinate - (24, 164) + (24, 196) _rotation From 50098ee8790389e45a8cf0d8e09f6fc27748dd30 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Sun, 22 Jan 2017 19:33:36 +0200 Subject: [PATCH 14/26] Dev (#53) * UDP Message source can handle multiple data types * Add a waterfall sink block * Fix dependency issues with VOLK * Add mean and max hold mode to the waterfall sink * Add mean and max hold mode to the waterfall sink * Install satnogs_waterfall.gp gnuplot script at /share/satnogs/scripts * Automatically retrieve x and y axis ranges at the satnogs_waterfall.gp --- CMakeLists.txt | 1 + apps/CMakeLists.txt | 1 + apps/scripts/CMakeLists.txt | 4 + apps/scripts/satnogs_waterfall.gp | 60 +++++++ grc/CMakeLists.txt | 2 +- grc/satnogs_block_tree.xml | 1 + grc/satnogs_udp_msg_source.xml | 20 ++- grc/satnogs_waterfall_sink.xml | 67 ++++++++ include/satnogs/CMakeLists.txt | 2 +- include/satnogs/udp_msg_source.h | 5 +- include/satnogs/waterfall_sink.h | 77 +++++++++ lib/CMakeLists.txt | 15 +- lib/udp_msg_source_impl.cc | 102 +++++++----- lib/udp_msg_source_impl.h | 4 +- lib/waterfall_sink_impl.cc | 268 ++++++++++++++++++++++++++++++ lib/waterfall_sink_impl.h | 86 ++++++++++ python/__init__.py | 7 +- swig/satnogs_swig.i | 22 +++ 18 files changed, 695 insertions(+), 49 deletions(-) create mode 100644 apps/scripts/CMakeLists.txt create mode 100755 apps/scripts/satnogs_waterfall.gp create mode 100644 grc/satnogs_waterfall_sink.xml create mode 100644 include/satnogs/waterfall_sink.h create mode 100644 lib/waterfall_sink_impl.cc create mode 100644 lib/waterfall_sink_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d08bd10..578a050 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ find_package (Threads REQUIRED) ######################################################################## find_package(CppUnit) find_package(Doxygen) +find_package(Volk REQUIRED) ######################################################################## # Include or not into the module blocks for debugging diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 65be159..f944868 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -20,6 +20,7 @@ include(GrPython) add_subdirectory(flowgraphs/satellites) +add_subdirectory(scripts) GR_PYTHON_INSTALL( PROGRAMS diff --git a/apps/scripts/CMakeLists.txt b/apps/scripts/CMakeLists.txt new file mode 100644 index 0000000..4355ed3 --- /dev/null +++ b/apps/scripts/CMakeLists.txt @@ -0,0 +1,4 @@ +INSTALL(FILES + satnogs_waterfall.gp + DESTINATION share/satnogs/scripts +) \ No newline at end of file diff --git a/apps/scripts/satnogs_waterfall.gp b/apps/scripts/satnogs_waterfall.gp new file mode 100755 index 0000000..60dfab0 --- /dev/null +++ b/apps/scripts/satnogs_waterfall.gp @@ -0,0 +1,60 @@ +#!/usr/bin/gnuplot +# +# gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module +# +# Copyright (C) 2017, 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 +# + +reset +if (!exists("height")) height=800 +if (!exists("width")) width=800 +if (!exists("outfile")) outfile='/tmp/waterfall.png' + +set terminal pngcairo size height,width enhanced font 'Verdana,14' +set output outfile + +unset key +set style line 11 lc rgb '#808080' lt 1 +set border 3 front ls 11 +set style line 12 lc rgb '#888888' lt 0 lw 1 +set grid front ls 12 +set tics nomirror out scale 0.75 + +set xlabel 'Frequency (kHz)' +set ylabel 'Time' +set cbtics scale 0 + +# palette +set palette defined (0 '#3288BD',\ + 1 '#66C2A5',\ + 2 '#ABDDA4',\ + 3 '#E6F598',\ + 4 '#FEE08B',\ + 5 '#FDAE61',\ + 6 '#F46D43',\ + 7 '#D53E4F') +set ylabel 'Time (seconds)' +set cbrange [-110:-20] +set cblabel 'Power (dB)' + +# Get automatically the axis ranges from the file +stats inputfile using 1 binary nooutput +set xrange [STATS_min*1e-3:STATS_max*1e-3 + 1] +stats inputfile using 2 binary nooutput +set yrange [0:STATS_max + 1] + +# Plot and scale the frequency axis to kHz for readability +plot inputfile using ($1*1e-3):2:3 binary matrix with image diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 90cdd05..40a7195 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -40,12 +40,12 @@ list(APPEND enabled_blocks satnogs_coarse_doppler_correction_cc.xml satnogs_ax25_encoder_mb.xml satnogs_ax25_decoder_bm.xml + satnogs_waterfall_sink.xml ) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND enabled_blocks ${debug_blocks}) endif() - install(FILES ${enabled_blocks} DESTINATION share/gnuradio/grc/blocks diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index 345437f..ee61c74 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -22,4 +22,5 @@ satnogs_coarse_doppler_correction_cc satnogs_ax25_encoder_mb satnogs_ax25_decoder_bm + satnogs_waterfall_sink \ No newline at end of file diff --git a/grc/satnogs_udp_msg_source.xml b/grc/satnogs_udp_msg_source.xml index d39e03c..10a8eec 100644 --- a/grc/satnogs_udp_msg_source.xml +++ b/grc/satnogs_udp_msg_source.xml @@ -3,7 +3,7 @@ UDP Message Source satnogs_udp_msg_source import satnogs - satnogs.udp_msg_source($addr, $port, $mtu) + satnogs.udp_msg_source($addr, $port, $mtu, $msg_type) IP Address @@ -25,6 +25,24 @@ 1500 int + + + Message Type + msg_type + enum + + + + msg diff --git a/grc/satnogs_waterfall_sink.xml b/grc/satnogs_waterfall_sink.xml new file mode 100644 index 0000000..9bf1e90 --- /dev/null +++ b/grc/satnogs_waterfall_sink.xml @@ -0,0 +1,67 @@ + + + Waterfall Sink + satnogs_waterfall_sink + import satnogs + satnogs.waterfall_sink($samp_rate, $center_freq, $pps, $fft_size, $filename, $mode) + + + Sample Rate + samp_rate + samp_rate + real + + + + FFT Size + fft_size + 1024 + int + + + + + Pixel Rows per Second + pps + 10 + int + + + + Mode + mode + enum + + + + + + + Center Frequency + center_freq + 0.0 + real + + + + File + filename + + file_save + + + + in + complex + + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index c91e88f..847f492 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -54,12 +54,12 @@ list(APPEND HEADER_FILES ax25_encoder_mb.h ax25_decoder_bm.h qb50_deframer.h + waterfall_sink.h ) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND HEADER_FILES ${DEBUG_HEADER_FILES}) endif() - install(FILES ${HEADER_FILES} DESTINATION include/satnogs diff --git a/include/satnogs/udp_msg_source.h b/include/satnogs/udp_msg_source.h index 75003a0..ad6b45e 100644 --- a/include/satnogs/udp_msg_source.h +++ b/include/satnogs/udp_msg_source.h @@ -48,9 +48,12 @@ namespace gr * @param addr the address to bind the UDP socket * @param port the UDP port to wait for packets * @param mtu the maximum MTU. Used to pre-allocate a maximum packet size + * @param type code of the data type of each message. 0 corresponds to raw + * bytes, 1 to 32-bit signed integers and 2 to 3 bit unsigned integers. */ static sptr - make (const std::string& addr, uint16_t port, size_t mtu = 1500); + make (const std::string& addr, uint16_t port, size_t mtu = 1500, + size_t type = 0); }; } // namespace satnogs diff --git a/include/satnogs/waterfall_sink.h b/include/satnogs/waterfall_sink.h new file mode 100644 index 0000000..ee0d654 --- /dev/null +++ b/include/satnogs/waterfall_sink.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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_WATERFALL_SINK_H +#define INCLUDED_SATNOGS_WATERFALL_SINK_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief This block computes the waterfall of the incoming signal + * and stores the result to a file. + * + * The file has a special header, so that the satnogs_waterfall Gnuplot + * script to be able to plot it properly. + * + * \ingroup satnogs + * + */ + class SATNOGS_API waterfall_sink : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /** + * This block computes the waterfall of the incoming signal + * and stores the result to a file. + * + * The file has a special header, so that the satnogs_waterfall Gnuplot + * script to be able to plot it properly. + * + * @param samp_rate the sampling rate + * @param center_freq the observation center frequency. Used only for + * plotting reasons. For a normalized frequency x-axis set it to 0. + * @param pps pixels per second + * @param fft_size FFT size + * @param filename the name of the output file + * @param mode the mode that the waterfall. + * - 0: Simple decimation + * - 1: Max hold + * - 2: Mean energy + * + * @return shared pointer to the object + */ + static sptr + make (double samp_rate, double center_freq, + double pps, size_t fft_size, + const std::string& filename, int mode = 0); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_WATERFALL_SINK_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 46201a5..aeb1960 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -22,7 +22,11 @@ ######################################################################## include(GrPlatform) #define LIB_SUFFIX -include_directories(${Boost_INCLUDE_DIR}) +include_directories( + ${Boost_INCLUDE_DIR} + ${VOLK_INCLUDE_DIRS} +) + link_directories(${Boost_LIBRARY_DIRS}) list(APPEND satnogs_debug_sources @@ -31,7 +35,6 @@ list(APPEND satnogs_debug_sources debug_msg_source_raw_impl.cc leo_channel_impl.cc ) - list(APPEND satnogs_sources cw_matched_filter_ff_impl.cc morse_tree.cc @@ -52,7 +55,8 @@ list(APPEND satnogs_sources coarse_doppler_correction_cc_impl.cc ax25_encoder_mb_impl.cc ax25_decoder_bm_impl.cc - qb50_deframer_impl.cc ) + qb50_deframer_impl.cc + waterfall_sink_impl.cc ) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) @@ -68,8 +72,11 @@ add_library(gnuradio-satnogs SHARED ${satnogs_sources}) target_link_libraries(gnuradio-satnogs ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} + gnuradio-digital ${CMAKE_THREAD_LIBS_INIT} - ${NOVA_LIBRARIES}) + ${NOVA_LIBRARIES} + ${VOLK_LIBRARIES} +) set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") diff --git a/lib/udp_msg_source_impl.cc b/lib/udp_msg_source_impl.cc index ba2566e..7521537 100644 --- a/lib/udp_msg_source_impl.cc +++ b/lib/udp_msg_source_impl.cc @@ -33,37 +33,37 @@ #include #include - namespace gr { namespace satnogs { udp_msg_source::sptr - udp_msg_source::make (const std::string& addr, uint16_t port, size_t mtu) + udp_msg_source::make (const std::string& addr, uint16_t port, size_t mtu, + size_t type) { return gnuradio::get_initial_sptr ( - new udp_msg_source_impl (addr, port, mtu)); + new udp_msg_source_impl (addr, port, mtu, type)); } /* * The private constructor */ udp_msg_source_impl::udp_msg_source_impl (const std::string& addr, - uint16_t port, - size_t mtu) : - gr::block ("udp_msg_source", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_iface_addr (addr), - d_udp_port (port), - d_mtu(mtu), - d_running (true) + uint16_t port, size_t mtu, + size_t type) : + gr::block ("udp_msg_source", gr::io_signature::make (0, 0, 0), + gr::io_signature::make (0, 0, 0)), + d_iface_addr (addr), + d_udp_port (port), + d_mtu (mtu), + d_type (type), + d_running (true) { - message_port_register_out(pmt::mp("msg")); + message_port_register_out (pmt::mp ("msg")); boost::shared_ptr ( - new boost::thread ( - boost::bind (&udp_msg_source_impl::udp_msg_accepter, this))); + new boost::thread ( + boost::bind (&udp_msg_source_impl::udp_msg_accepter, this))); } void @@ -75,10 +75,13 @@ namespace gr socklen_t client_addr_len; ssize_t ret; uint8_t *buf; + uint32_t bytes_num; + uint32_t uint_val; + uint32_t int_val; if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - perror ("opening UDP socket"); - exit (EXIT_FAILURE); + perror ("opening UDP socket"); + exit (EXIT_FAILURE); } memset (&client_addr, 0, sizeof(struct sockaddr)); @@ -86,35 +89,60 @@ namespace gr sin.sin_family = AF_INET; sin.sin_port = htons (d_udp_port); - if( inet_aton(d_iface_addr.c_str(), &(sin.sin_addr)) == 0){ - LOG_ERROR("Wrong IP address"); - close(sock); - exit (EXIT_FAILURE); + if (inet_aton (d_iface_addr.c_str (), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close (sock); + exit (EXIT_FAILURE); } if (bind (sock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) - == -1) { - perror ("UDP bind"); - close(sock); - exit (EXIT_FAILURE); + == -1) { + perror ("UDP bind"); + close (sock); + exit (EXIT_FAILURE); } /* All good until now. Allocate buffer memory and proceed */ buf = new uint8_t[d_mtu]; - while(d_running){ - ret = recvfrom(sock, buf, d_mtu, 0, &client_addr, &client_addr_len); - if(ret > 0) { - message_port_pub(pmt::mp("msg"), pmt::make_blob(buf, ret)); - } - else{ - perror("UDP recvfrom"); - close(sock); - delete[] buf; - exit(EXIT_FAILURE); - } + while (d_running) { + ret = recvfrom (sock, buf, d_mtu, 0, &client_addr, &client_addr_len); + if (ret > 0) { + bytes_num = (uint32_t) ret; + switch(d_type){ + case 0: + message_port_pub (pmt::mp ("msg"), pmt::make_blob (buf, bytes_num)); + case 1: + if(bytes_num < sizeof(uint32_t)){ + continue; + } + memcpy(&uint_val, buf, sizeof(uint32_t)); + message_port_pub (pmt::mp ("msg"), + pmt::from_uint64 (ntohl (uint_val))); + break; + case 2: + if (bytes_num < sizeof(int32_t)) { + continue; + } + memcpy(&int_val, buf, sizeof(int32_t)); + message_port_pub (pmt::mp ("msg"), + pmt::from_long (ntohl (int_val))); + break; + default: + LOG_ERROR("Unsupported message type"); + close (sock); + delete[] buf; + exit (EXIT_FAILURE); + } + } + else { + perror ("UDP recvfrom"); + close (sock); + delete[] buf; + exit (EXIT_FAILURE); + } } - close(sock); + close (sock); delete[] buf; exit (EXIT_SUCCESS); } diff --git a/lib/udp_msg_source_impl.h b/lib/udp_msg_source_impl.h index 36736f5..4c4c810 100644 --- a/lib/udp_msg_source_impl.h +++ b/lib/udp_msg_source_impl.h @@ -35,6 +35,7 @@ namespace gr const std::string d_iface_addr; const uint16_t d_udp_port; const size_t d_mtu; + const size_t d_type; bool d_running; boost::shared_ptr d_thread; @@ -42,7 +43,8 @@ namespace gr udp_msg_accepter (); public: - udp_msg_source_impl (const std::string& addr, uint16_t port, size_t mtu); + udp_msg_source_impl (const std::string& addr, uint16_t port, + size_t mtu, size_t type); ~udp_msg_source_impl (); }; diff --git a/lib/waterfall_sink_impl.cc b/lib/waterfall_sink_impl.cc new file mode 100644 index 0000000..94c1f30 --- /dev/null +++ b/lib/waterfall_sink_impl.cc @@ -0,0 +1,268 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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 "waterfall_sink_impl.h" +#include +namespace gr +{ + namespace satnogs + { + + waterfall_sink::sptr + waterfall_sink::make (double samp_rate, double center_freq, + double fps, size_t fft_size, + const std::string& filename, int mode) + { + return gnuradio::get_initial_sptr ( + new waterfall_sink_impl (samp_rate, center_freq, + fps, fft_size, filename, mode)); + } + + /* + * The private constructor + */ + waterfall_sink_impl::waterfall_sink_impl (double samp_rate, + double center_freq, + double pps, + size_t fft_size, + const std::string& filename, + int mode) : + gr::sync_block ("waterfall_sink", + gr::io_signature::make (1, 1, sizeof(gr_complex)), + gr::io_signature::make (0, 0, 0)), + d_samp_rate (samp_rate), + d_pps (pps), + d_fft_size (fft_size), + d_mode ((wf_mode_t)mode), + d_refresh( (d_samp_rate / fft_size) / pps), + d_fft_cnt(0), + d_fft_shift((size_t)(ceil(fft_size/2.0))), + d_samples_cnt(0), + d_fft (fft_size) + { + float r = 0.0; + const int alignment_multiple = volk_get_alignment () + / (fft_size * sizeof(gr_complex)); + set_alignment (std::max (1, alignment_multiple)); + set_output_multiple (fft_size); + + d_shift_buffer = (gr_complex *) volk_malloc ( + fft_size * sizeof(gr_complex), volk_get_alignment()); + if(!d_shift_buffer){ + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error("Could not allocate aligned memory"); + } + + d_hold_buffer = (float *)volk_malloc(fft_size * sizeof(gr_complex), + volk_get_alignment()); + if(!d_hold_buffer){ + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error("Could not allocate aligned memory"); + } + memset(d_hold_buffer, 0, fft_size * sizeof(gr_complex)); + + d_tmp_buffer = (float *) volk_malloc (fft_size * sizeof(float), + volk_get_alignment ()); + if (!d_tmp_buffer) { + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error ("Could not allocate aligned memory"); + } + + d_fos.open(filename, std::ios::binary | std::ios::trunc); + + /* Append header for proper plotting */ + r = fft_size; + d_fos.write((char *)&r, sizeof(float)); + for(size_t i = 0; i < fft_size; i++) { + r = (samp_rate/fft_size * i ) - samp_rate/2.0 + center_freq; + d_fos.write((char *)&r, sizeof(float)); + } + } + + /* + * Our virtual destructor. + */ + waterfall_sink_impl::~waterfall_sink_impl () + { + d_fos.close(); + volk_free(d_shift_buffer); + volk_free(d_hold_buffer); + volk_free(d_tmp_buffer); + } + + int + waterfall_sink_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]; + size_t n_fft = ((size_t) noutput_items / d_fft_size); + + switch (d_mode) + { + case WATERFALL_MODE_DECIMATION: + compute_decimation (in, n_fft); + break; + case WATERFALL_MODE_MAX_HOLD: + compute_max_hold (in, n_fft); + break; + case WATERFALL_MODE_MEAN: + compute_mean (in, n_fft); + break; + default: + LOG_ERROR("Wrong waterfall mode"); + throw std::runtime_error ("Wrong waterfall mode"); + return -1; + } + + return n_fft * d_fft_size; + } + + void + waterfall_sink_impl::compute_decimation (const gr_complex* in, size_t n_fft) + { + size_t i; + float t; + gr_complex *fft_in; + for(i = 0; i < n_fft; i++){ + d_fft_cnt++; + if(d_fft_cnt > d_refresh){ + fft_in = d_fft.get_inbuf(); + memcpy(fft_in, in + i*d_fft_size, d_fft_size*sizeof(gr_complex)); + d_fft.execute(); + /* Perform FFT shift */ + memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); + + /* Compute the energy in dB */ + volk_32fc_s32f_x2_power_spectral_density_32f (d_hold_buffer, + d_shift_buffer, + (float) d_fft_size, 1.0, + d_fft_size); + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); + d_fft_cnt = 0; + } + d_samples_cnt += d_fft_size; + } + } + + void + waterfall_sink_impl::compute_max_hold (const gr_complex* in, size_t n_fft) + { + size_t i; + size_t j; + float t; + gr_complex *fft_in; + for(i = 0; i < n_fft; i++){ + fft_in = d_fft.get_inbuf (); + memcpy (fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); + d_fft.execute (); + /* Perform FFT shift */ + memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); + + /* Normalization factor */ + volk_32fc_s32fc_multiply_32fc(d_shift_buffer, d_shift_buffer, + 1.0/d_fft_size, d_fft_size); + + /* Compute the mag^2 */ + volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_shift_buffer, + d_fft_size); + /* Max hold */ + volk_32f_x2_max_32f (d_hold_buffer, d_hold_buffer, d_tmp_buffer, + d_fft_size); + d_fft_cnt++; + if(d_fft_cnt > d_refresh) { + /* Compute the energy in dB */ + for(j = 0; j < d_fft_size; j++){ + d_hold_buffer[j] = 10.0 * log10f(d_hold_buffer[j] + 1.0e-20); + } + + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); + + /* Reset */ + d_fft_cnt = 0; + memset(d_hold_buffer, 0, d_fft_size * sizeof(float)); + } + d_samples_cnt += d_fft_size; + } + } + + void + waterfall_sink_impl::compute_mean (const gr_complex* in, size_t n_fft) + { + size_t i; + size_t j; + float t; + gr_complex *fft_in; + for(i = 0; i < n_fft; i++){ + fft_in = d_fft.get_inbuf (); + memcpy (fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); + d_fft.execute (); + /* Perform FFT shift */ + memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); + + /* Accumulate the complex numbers */ + volk_32f_x2_add_32f(d_hold_buffer, d_hold_buffer, + (float *)d_shift_buffer, 2 * d_fft_size); + d_fft_cnt++; + if(d_fft_cnt > d_refresh) { + /* + * Compute the energy in dB performing the proper normalization + * before any dB calculation, emulating the mean + */ + volk_32fc_s32f_x2_power_spectral_density_32f ( + d_hold_buffer, (gr_complex *)d_hold_buffer, + (float) d_fft_cnt * d_fft_size, 1.0, d_fft_size); + + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); + + /* Reset */ + d_fft_cnt = 0; + memset(d_hold_buffer, 0, 2 * d_fft_size * sizeof(float)); + } + d_samples_cnt += d_fft_size; + } + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/waterfall_sink_impl.h b/lib/waterfall_sink_impl.h new file mode 100644 index 0000000..cf80b44 --- /dev/null +++ b/lib/waterfall_sink_impl.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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_WATERFALL_SINK_IMPL_H +#define INCLUDED_SATNOGS_WATERFALL_SINK_IMPL_H + +#include +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + class waterfall_sink_impl : public waterfall_sink + { + private: + /** + * The different types of operation of the waterfall + */ + typedef enum { + WATERFALL_MODE_DECIMATION = 0,//!< WATERFALL_MODE_DECIMATION Performs just a decimation and computes the energy only + WATERFALL_MODE_MAX_HOLD = 1, //!< WATERFALL_MODE_MAX_HOLD compute the max hold energy of all the FFT snapshots between two consecutive pixel rows + WATERFALL_MODE_MEAN = 2 //!< WATERFALL_MODE_MEAN compute the mean energy of all the FFT snapshots between two consecutive pixel rows + } wf_mode_t; + + const double d_samp_rate; + double d_pps; + const size_t d_fft_size; + wf_mode_t d_mode; + size_t d_refresh; + size_t d_fft_cnt; + size_t d_fft_shift; + size_t d_samples_cnt; + fft::fft_complex d_fft; + gr_complex *d_shift_buffer; + float *d_hold_buffer; + float *d_tmp_buffer; + std::ofstream d_fos; + + public: + waterfall_sink_impl (double samp_rate, double center_freq, + double pps, size_t fft_size, + const std::string& filename, int mode); + ~waterfall_sink_impl (); + + + int + work (int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void + compute_decimation(const gr_complex *in, size_t n_fft); + + void + compute_max_hold(const gr_complex *in, size_t n_fft); + + void + compute_mean(const gr_complex *in, size_t n_fft); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_WATERFALL_SINK_IMPL_H */ + diff --git a/python/__init__.py b/python/__init__.py index 80199ba..58de6ce 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -22,6 +22,7 @@ This is the GNU Radio SATNOGS module. Place your Python package description here (python/__init__.py). ''' +import sys # import swig generated symbols into the satnogs namespace try: @@ -30,8 +31,8 @@ try: from dsp_settings import * from hw_settings import * from satnogs_upsat_transmitter import * -except ImportError: +except ImportError as err: + sys.stderr.write("Failed to import SatNOGS ({})\n".format(err)) + sys.stderr.write("Consider first to run 'sudo ldconfig'\n") pass -# import any pure python here -# diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index de1f8f0..4c6b730 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -30,18 +30,24 @@ #include "satnogs/ax25_encoder_mb.h" #include "satnogs/ax25_decoder_bm.h" #include "satnogs/qb50_deframer.h" +#include "satnogs/waterfall_sink.h" %} %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/multi_format_msg_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, multi_format_msg_sink); + %include "satnogs/cw_to_symbol.h" GR_SWIG_BLOCK_MAGIC2(satnogs, cw_to_symbol); @@ -50,28 +56,44 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, sine_matched_filter_ff); %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); + %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); + %include "satnogs/upsat_fsk_frame_acquisition.h" GR_SWIG_BLOCK_MAGIC2(satnogs, upsat_fsk_frame_acquisition); + %include "satnogs/upsat_fsk_frame_encoder.h" GR_SWIG_BLOCK_MAGIC2(satnogs, upsat_fsk_frame_encoder); + %include "satnogs/whitening.h" + %include "satnogs/udp_msg_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, udp_msg_sink); + %include "satnogs/coarse_doppler_correction_cc.h" GR_SWIG_BLOCK_MAGIC2(satnogs, coarse_doppler_correction_cc); + %include "satnogs/debug_msg_source_raw.h" GR_SWIG_BLOCK_MAGIC2(satnogs, debug_msg_source_raw); + %include "satnogs/ax25_encoder_mb.h" GR_SWIG_BLOCK_MAGIC2(satnogs, ax25_encoder_mb); + %include "satnogs/ax25_decoder_bm.h" GR_SWIG_BLOCK_MAGIC2(satnogs, ax25_decoder_bm); + %include "satnogs/qb50_deframer.h" GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer); + +%include "satnogs/waterfall_sink.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink); From 7184f551a09d9d03aebf2200b888d7f2329ad0e9 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Sun, 22 Jan 2017 12:36:13 -0500 Subject: [PATCH 15/26] Change fm_demod to quadrature demod (#51) Taking out WBFM/NBFM for a straight quadrature demod method Change from 44.1k output to 44k output to be more compatible with gr-satellites Also changing rtlsdr to a 2msps rate by default --- apps/flowgraphs/fm_demod.grc | 666 +++++----------------------- apps/flowgraphs/satnogs_fm_demod.py | 79 ++-- python/hw_settings.py | 2 +- 3 files changed, 148 insertions(+), 599 deletions(-) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index fd5f6f3..35abf0b 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -10,7 +10,7 @@ window_size - 3000,3000 + 3000, 3000 category @@ -81,33 +81,6 @@ FM Generic Demodulation - - variable - - comment - - - - _enabled - True - - - _coordinate - (1864, 12) - - - _rotation - 0 - - - id - audio_decimation - - - value - 2 - - variable @@ -122,7 +95,7 @@ SDR received samples _coordinate - (1296, 12) + (1704, 796) _rotation @@ -149,7 +122,7 @@ SDR received samples _coordinate - (2072, 12) + (1704, 52) _rotation @@ -161,7 +134,7 @@ SDR received samples value - 44100 + 48000 @@ -174,11 +147,11 @@ SDR received samples _enabled - True + 0 _coordinate - (1088, 12) + (1704, 348) _rotation @@ -205,7 +178,61 @@ SDR received samples _coordinate - (1680, 12) + (1480, 988) + + + _rotation + 0 + + + id + deviation + + + value + 5000 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (1704, 260) + + + _rotation + 0 + + + id + filter_rate + + + value + 250000 + + + + variable + + comment + + + + _enabled + 0 + + + _coordinate + (1704, 508) _rotation @@ -233,7 +260,7 @@ TX sampling rate _coordinate - (1512, 12) + (1704, 956) _rotation @@ -268,7 +295,7 @@ TX sampling rate _coordinate - (32, 788) + (48, 716) _rotation @@ -296,34 +323,18 @@ TX sampling rate - analog_sig_source_x - - amp - 1 - - - alias - - + variable comment - - affinity - - _enabled - 0 - - - freq - -lo_offset + True _coordinate - (320, 12) + (1704, 164) _rotation @@ -331,39 +342,15 @@ TX sampling rate id - analog_sig_source_x_0 + xlate_filter_taps - maxoutbuf - 0 - - - minoutbuf - 0 - - - offset - 0 - - - type - complex - - - samp_rate - samp_rate_rx - - - waveform - analog.GR_COS_WAVE + value + firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76) - analog_wfm_rcv - - audio_decimation - audio_decimation - + analog_quadrature_demod_cf alias @@ -378,19 +365,23 @@ TX sampling rate _enabled - 1 + True _coordinate - (1176, 476) + (1088, 564) _rotation - 0 + 180 + + + gain + (2*math.pi*deviation)/audio_samp_rate id - analog_wfm_rcv_0 + analog_quadrature_demod_cf_0 maxoutbuf @@ -400,64 +391,9 @@ TX sampling rate minoutbuf 0 - - quad_rate - quadrature_rate - - blocks_multiply_const_vxx - - alias - - - - comment - - - - const - audio_gain - - - affinity - - - - _enabled - 1 - - - _coordinate - (1808, 484) - - - _rotation - 0 - - - id - blocks_multiply_const_vxx_0 - - - type - float - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - vlen - 1 - - - - blocks_multiply_xx + rational_resampler_xxx alias @@ -470,13 +406,21 @@ TX sampling rate affinity + + decim + 125 + _enabled + True + + + fbw 0 _coordinate - (568, 140) + (1272, 268) _rotation @@ -484,11 +428,11 @@ TX sampling rate id - blocks_multiply_xx_0 + blks2_rational_resampler_xxx_1 - type - complex + interp + 24 maxoutbuf @@ -499,12 +443,12 @@ TX sampling rate 0 - num_inputs - 2 + taps + [] - vlen - 1 + type + ccc @@ -535,7 +479,7 @@ TX sampling rate _coordinate - (2056, 464) + (1088, 664) _rotation @@ -570,7 +514,7 @@ TX sampling rate _coordinate - (1904, 192) + (64, 984) _rotation @@ -613,7 +557,7 @@ TX sampling rate _coordinate - (1272, 192) + (736, 984) _rotation @@ -660,7 +604,7 @@ TX sampling rate decim - decimation_rx + int(samp_rate_rx/filter_rate) _enabled @@ -668,7 +612,7 @@ TX sampling rate _coordinate - (808, 452) + (680, 268) _rotation @@ -692,7 +636,7 @@ TX sampling rate taps - taps + xlate_filter_taps type @@ -716,7 +660,7 @@ we shift the LO a little further _coordinate - (1736, 192) + (1704, 608) _rotation @@ -2047,7 +1991,7 @@ we shift the LO a little further _coordinate - (16, 368) + (16, 376) _rotation @@ -2150,368 +2094,6 @@ we shift the LO a little further - - pfb_arb_resampler_xxx - - alias - - - - comment - - - - affinity - - - - _enabled - 1 - - - _coordinate - (1456, 452) - - - _rotation - 0 - - - id - pfb_arb_resampler_xxx_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - nfilts - 32 - - - rrate - audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation) - - - samp_delay - 0 - - - atten - 100 - - - taps - firdes.low_pass_2(32, 32, 0.8, 0.1, 100) - - - type - fff - - - - qtgui_freq_sink_x - - autoscale - False - - - average - 1.0 - - - axislabels - True - - - bw - samp_rate_rx - - - alias - - - - fc - 0 - - - comment - - - - ctrlpanel - True - - - affinity - - - - _enabled - 0 - - - fftsize - 1024 - - - _coordinate - (728, 120) - - - gui_hint - - - - _rotation - 0 - - - grid - True - - - id - qtgui_freq_sink_x_0 - - - legend - True - - - alpha1 - 1.0 - - - color1 - "blue" - - - label1 - - - - width1 - 1 - - - alpha10 - 1.0 - - - color10 - "dark blue" - - - label10 - - - - width10 - 1 - - - alpha2 - 1.0 - - - color2 - "red" - - - label2 - - - - width2 - 1 - - - alpha3 - 1.0 - - - color3 - "green" - - - label3 - - - - width3 - 1 - - - alpha4 - 1.0 - - - color4 - "black" - - - label4 - - - - width4 - 1 - - - alpha5 - 1.0 - - - color5 - "cyan" - - - label5 - - - - width5 - 1 - - - alpha6 - 1.0 - - - color6 - "magenta" - - - label6 - - - - width6 - 1 - - - alpha7 - 1.0 - - - color7 - "yellow" - - - label7 - - - - width7 - 1 - - - alpha8 - 1.0 - - - color8 - "dark red" - - - label8 - - - - width8 - 1 - - - alpha9 - 1.0 - - - color9 - "dark green" - - - label9 - - - - width9 - 1 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - name - "" - - - nconnections - 1 - - - showports - True - - - freqhalf - True - - - tr_chan - 0 - - - tr_level - 0.0 - - - tr_mode - qtgui.TRIG_MODE_FREE - - - tr_tag - "" - - - type - complex - - - update_time - 0.01 - - - wintype - firdes.WIN_BLACKMAN_hARRIS - - - label - Relative Gain - - - ymax - 10 - - - ymin - -140 - - - units - dB - - parameter @@ -2528,7 +2110,7 @@ we shift the LO a little further _coordinate - (1576, 192) + (472, 984) _rotation @@ -2571,7 +2153,7 @@ we shift the LO a little further _coordinate - (1432, 192) + (616, 984) _rotation @@ -2614,7 +2196,7 @@ we shift the LO a little further _coordinate - (1080, 192) + (312, 984) _rotation @@ -2661,7 +2243,7 @@ we shift the LO a little further _coordinate - (464, 460) + (352, 276) _rotation @@ -2708,7 +2290,7 @@ we shift the LO a little further _coordinate - (24, 196) + (16, 204) _rotation @@ -2748,53 +2330,29 @@ we shift the LO a little further - analog_sig_source_x_0 - blocks_multiply_xx_0 - 0 - 0 - - - analog_wfm_rcv_0 - pfb_arb_resampler_xxx_0 - 0 - 0 - - - blocks_multiply_const_vxx_0 + analog_quadrature_demod_cf_0 blocks_wavfile_sink_0 0 0 - blocks_multiply_xx_0 - qtgui_freq_sink_x_0 + blks2_rational_resampler_xxx_1 + analog_quadrature_demod_cf_0 0 0 freq_xlating_fir_filter_xxx_0 - analog_wfm_rcv_0 + blks2_rational_resampler_xxx_1 0 0 - - osmosdr_source_0 - blocks_multiply_xx_0 - 0 - 1 - osmosdr_source_0 satnogs_coarse_doppler_correction_cc_0 0 0 - - pfb_arb_resampler_xxx_0 - blocks_multiply_const_vxx_0 - 0 - 0 - satnogs_coarse_doppler_correction_cc_0 freq_xlating_fir_filter_xxx_0 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index c78df64..b8d85ed 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Nov 7 19:50:22 2016 +# Generated: Fri Jan 20 15:58:24 2017 ################################################## from gnuradio import analog @@ -15,8 +15,8 @@ from gnuradio import filter from gnuradio import gr from gnuradio.eng_option import eng_option from gnuradio.filter import firdes -from gnuradio.filter import pfb from optparse import OptionParser +import math import osmosdr import satnogs import time @@ -41,26 +41,20 @@ class satnogs_fm_demod(gr.top_block): # Variables ################################################## self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] - self.decimation_rx = decimation_rx = satnogs.fm_demod_settings[rx_sdr_device]['decimation_rx'] + self.xlate_filter_taps = xlate_filter_taps = firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76) self.taps = taps = firdes.low_pass(12.0, samp_rate_rx, 100e3, 60000, firdes.WIN_HAMMING, 6.76) - self.quadrature_rate = quadrature_rate = samp_rate_rx / decimation_rx - self.audio_samp_rate = audio_samp_rate = 44100 + self.filter_rate = filter_rate = 250000 + self.deviation = deviation = 5000 + self.audio_samp_rate = audio_samp_rate = 48000 self.audio_gain = audio_gain = satnogs.fm_demod_settings[rx_sdr_device]['audio_gain'] - self.audio_decimation = audio_decimation = 2 ################################################## # Blocks ################################################## self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) - self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( - audio_samp_rate / (quadrature_rate * 1.0 / audio_decimation), - taps=(firdes.low_pass_2(32, 32, 0.8, 0.1, 100)), - flt_size=32) - self.pfb_arb_resampler_xxx_0.declare_sample_delay(0) - self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) self.osmosdr_source_0.set_sample_rate(samp_rate_rx) self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) @@ -74,23 +68,24 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0) self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) - self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(decimation_rx, (taps), lo_offset, samp_rate_rx) + self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(int(samp_rate_rx/filter_rate), (xlate_filter_taps), lo_offset, samp_rate_rx) self.blocks_wavfile_sink_0 = blocks.wavfile_sink(file_path, 1, audio_samp_rate, 16) - self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((audio_gain, )) - self.analog_wfm_rcv_0 = analog.wfm_rcv( - quad_rate=quadrature_rate, - audio_decimation=audio_decimation, + self.blks2_rational_resampler_xxx_1 = filter.rational_resampler_ccc( + interpolation=24, + decimation=125, + taps=None, + fractional_bw=None, ) + self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf((2*math.pi*deviation)/audio_samp_rate) ################################################## # Connections ################################################## self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) - self.connect((self.analog_wfm_rcv_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) - self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_wavfile_sink_0, 0)) - self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.analog_wfm_rcv_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0, 0), (self.blocks_wavfile_sink_0, 0)) + self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.analog_quadrature_demod_cf_0, 0)) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blks2_rational_resampler_xxx_1, 0)) self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) def get_doppler_correction_per_sec(self): @@ -134,63 +129,59 @@ class satnogs_fm_demod(gr.top_block): def set_rx_sdr_device(self, rx_sdr_device): self.rx_sdr_device = rx_sdr_device self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) - self.set_decimation_rx(satnogs.fm_demod_settings[self.rx_sdr_device]['decimation_rx']) - self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain']) self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0) self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0) self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0) self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0) + self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain']) def get_samp_rate_rx(self): return self.samp_rate_rx def set_samp_rate_rx(self, samp_rate_rx): self.samp_rate_rx = samp_rate_rx - self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + self.set_xlate_filter_taps(firdes.low_pass(1, self.samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76)) self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx) self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0) - def get_decimation_rx(self): - return self.decimation_rx + def get_xlate_filter_taps(self): + return self.xlate_filter_taps - def set_decimation_rx(self, decimation_rx): - self.decimation_rx = decimation_rx - self.set_quadrature_rate(self.samp_rate_rx / self.decimation_rx) + def set_xlate_filter_taps(self, xlate_filter_taps): + self.xlate_filter_taps = xlate_filter_taps + self.freq_xlating_fir_filter_xxx_0.set_taps((self.xlate_filter_taps)) def get_taps(self): return self.taps def set_taps(self, taps): self.taps = taps - self.freq_xlating_fir_filter_xxx_0.set_taps((self.taps)) - def get_quadrature_rate(self): - return self.quadrature_rate + def get_filter_rate(self): + return self.filter_rate - def set_quadrature_rate(self, quadrature_rate): - self.quadrature_rate = quadrature_rate - self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) + def set_filter_rate(self, filter_rate): + self.filter_rate = filter_rate + + def get_deviation(self): + return self.deviation + + def set_deviation(self, deviation): + self.deviation = deviation + self.analog_quadrature_demod_cf_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_rate) def get_audio_samp_rate(self): return self.audio_samp_rate def set_audio_samp_rate(self, audio_samp_rate): self.audio_samp_rate = audio_samp_rate - self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) + self.analog_quadrature_demod_cf_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_rate) def get_audio_gain(self): return self.audio_gain def set_audio_gain(self, audio_gain): self.audio_gain = audio_gain - self.blocks_multiply_const_vxx_0.set_k((self.audio_gain, )) - - def get_audio_decimation(self): - return self.audio_decimation - - def set_audio_decimation(self, audio_decimation): - self.audio_decimation = audio_decimation - self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate / (self.quadrature_rate * 1.0 / self.audio_decimation)) def argument_parser(): diff --git a/python/hw_settings.py b/python/hw_settings.py index 570b875..8ed7f94 100644 --- a/python/hw_settings.py +++ b/python/hw_settings.py @@ -46,5 +46,5 @@ hw_rx_settings = {'usrpb200' : {'rf_gain' : 20.0, 'if_gain' : 0.0, 'bb_gain' : 20.0, 'samp_rate' : 2e6, 'antenna' : '', 'dev_arg': 'hackrf'}, 'rtlsdr' : {'rf_gain' : 32.0, 'if_gain' : 0.0, - 'bb_gain' : 0.0, 'samp_rate' : 1.024e6, + 'bb_gain' : 0.0, 'samp_rate' : 2e6, 'antenna' : '', 'dev_arg' : 'rtl'} } From da4d89f2daca05cf9296f694bdc72eb4aaad3265 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Thu, 26 Jan 2017 08:36:35 -0500 Subject: [PATCH 16/26] waterfall fm_demod script fm_demod script that also writes waterfall data (credit to surligas, I'm just committing) Also FFT needs to be added to CMakeLists.txt to build in some conditions. see also satnogs/gr-satnogs#42 --- CMakeLists.txt | 2 +- apps/flowgraphs/fm_demod.grc | 108 +++++++++++++++++++++++++++- apps/flowgraphs/satnogs_fm_demod.py | 18 ++++- 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 578a050..c59725c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ endif() # components required to the list of GR_REQUIRED_COMPONENTS (in all # caps such as FILTER or FFT) and change the version to the minimum # API compatible version required. -set(GR_REQUIRED_COMPONENTS RUNTIME) +set(GR_REQUIRED_COMPONENTS RUNTIME FFT) find_package(Gnuradio "3.7.7" REQUIRED) if(NOT CPPUNIT_FOUND) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index 35abf0b..461cf59 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -557,11 +557,11 @@ TX sampling rate _coordinate - (736, 984) + (744, 988) _rotation - 0 + 180 id @@ -2329,6 +2329,104 @@ we shift the LO a little further 1000 + + satnogs_waterfall_sink + + alias + + + + center_freq + 0.0 + + + comment + + + + affinity + + + + _enabled + True + + + fft_size + 1024 + + + filename + waterfall_file_path + + + _coordinate + (1488, 248) + + + _rotation + 0 + + + id + satnogs_waterfall_sink_0 + + + mode + 1 + + + pps + 10 + + + samp_rate + audio_samp_rate + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (872, 988) + + + _rotation + 0 + + + id + waterfall_file_path + + + label + + + + short_id + + + + type + string + + + value + /tmp/waterfall.dat + + analog_quadrature_demod_cf_0 blocks_wavfile_sink_0 @@ -2341,6 +2439,12 @@ we shift the LO a little further 0 0 + + blks2_rational_resampler_xxx_1 + satnogs_waterfall_sink_0 + 0 + 0 + freq_xlating_fir_filter_xxx_0 blks2_rational_resampler_xxx_1 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index b8d85ed..f97acc4 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Fri Jan 20 15:58:24 2017 +# Generated: Mon Jan 23 20:10:12 2017 ################################################## from gnuradio import analog @@ -24,7 +24,7 @@ import time class satnogs_fm_demod(gr.top_block): - def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200'): + def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat'): gr.top_block.__init__(self, "FM Generic Demodulation") ################################################## @@ -36,6 +36,7 @@ class satnogs_fm_demod(gr.top_block): self.rigctl_port = rigctl_port self.rx_freq = rx_freq self.rx_sdr_device = rx_sdr_device + self.waterfall_file_path = waterfall_file_path ################################################## # Variables @@ -53,6 +54,7 @@ class satnogs_fm_demod(gr.top_block): ################################################## # Blocks ################################################## + self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 1024, waterfall_file_path, 1) self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) @@ -84,6 +86,7 @@ class satnogs_fm_demod(gr.top_block): self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) self.connect((self.analog_quadrature_demod_cf_0, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.analog_quadrature_demod_cf_0, 0)) + self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.satnogs_waterfall_sink_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blks2_rational_resampler_xxx_1, 0)) self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) @@ -135,6 +138,12 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0) self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain']) + def get_waterfall_file_path(self): + return self.waterfall_file_path + + def set_waterfall_file_path(self, waterfall_file_path): + self.waterfall_file_path = waterfall_file_path + def get_samp_rate_rx(self): return self.samp_rate_rx @@ -205,6 +214,9 @@ def argument_parser(): parser.add_option( "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200', help="Set rx_sdr_device [default=%default]") + parser.add_option( + "", "--waterfall-file-path", dest="waterfall_file_path", type="string", default='/tmp/waterfall.dat', + help="Set waterfall_file_path [default=%default]") return parser @@ -212,7 +224,7 @@ def main(top_block_cls=satnogs_fm_demod, options=None): if options is None: options, _ = argument_parser().parse_args() - tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device) + tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, waterfall_file_path=options.waterfall_file_path) tb.start() tb.wait() From 639c372a227db67f2dbd6d6f04e71d7c156c0a72 Mon Sep 17 00:00:00 2001 From: George Vardakis Date: Thu, 2 Feb 2017 21:05:02 +0200 Subject: [PATCH 17/26] Implement ogg encoder block --- grc/CMakeLists.txt | 2 +- grc/satnogs_ogg_enc.xml | 38 ++++++++++ include/satnogs/CMakeLists.txt | 2 +- include/satnogs/ogg_enc.h | 54 +++++++++++++ lib/CMakeLists.txt | 7 +- lib/ogg_enc_impl.cc | 135 +++++++++++++++++++++++++++++++++ lib/ogg_enc_impl.h | 61 +++++++++++++++ swig/satnogs_swig.i | 3 + 8 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 grc/satnogs_ogg_enc.xml create mode 100644 include/satnogs/ogg_enc.h create mode 100644 lib/ogg_enc_impl.cc create mode 100644 lib/ogg_enc_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 40a7195..40d66ab 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -48,5 +48,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${enabled_blocks} - DESTINATION share/gnuradio/grc/blocks + satnogs_ogg_enc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_ogg_enc.xml b/grc/satnogs_ogg_enc.xml new file mode 100644 index 0000000..d5a47f5 --- /dev/null +++ b/grc/satnogs_ogg_enc.xml @@ -0,0 +1,38 @@ + + + ogg_enc + satnogs_ogg_enc + [satnogs] + import satnogs + satnogs.ogg_enc($filename, $samp_rate, $quality) + + + ... + ... + ... + + + + + in + + + + + + out + + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 847f492..7f65a8a 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -62,5 +62,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${HEADER_FILES} - DESTINATION include/satnogs + ogg_enc.h DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/ogg_enc.h b/include/satnogs/ogg_enc.h new file mode 100644 index 0000000..45bf948 --- /dev/null +++ b/include/satnogs/ogg_enc.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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_OGG_ENCODER_H +#define INCLUDED_SATNOGS_OGG_ENCODER_H + +#include +#include + +namespace gr { + namespace satnogs { + + /*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ + class SATNOGS_API ogg_encoder : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of satnogs::ogg_encoder. + * + * To avoid accidental use of raw pointers, satnogs::ogg_encoder's + * constructor is in a private implementation + * class. satnogs::ogg_encoder::make is the public interface for + * creating new instances. + */ + static sptr make(char* filename, double samp_rate, float quality); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_OGG_ENCODER_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index aeb1960..8f7f8cd 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,6 +25,7 @@ include(GrPlatform) #define LIB_SUFFIX include_directories( ${Boost_INCLUDE_DIR} ${VOLK_INCLUDE_DIRS} + ${OGG_INCLUDE_DIRS} ) link_directories(${Boost_LIBRARY_DIRS}) @@ -56,7 +57,8 @@ list(APPEND satnogs_sources ax25_encoder_mb_impl.cc ax25_decoder_bm_impl.cc qb50_deframer_impl.cc - waterfall_sink_impl.cc ) + waterfall_sink_impl.cc + ogg_enc_impl.cc ) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) @@ -76,6 +78,9 @@ target_link_libraries(gnuradio-satnogs ${CMAKE_THREAD_LIBS_INIT} ${NOVA_LIBRARIES} ${VOLK_LIBRARIES} + ogg + vorbis + vorbisenc ) set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") diff --git a/lib/ogg_enc_impl.cc b/lib/ogg_enc_impl.cc new file mode 100644 index 0000000..8d63b73 --- /dev/null +++ b/lib/ogg_enc_impl.cc @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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 "ogg_encoder_impl.h" + +#include +#include +#include +#include +#include + + +namespace gr { + namespace satnogs { + + ogg_encoder::sptr + ogg_encoder::make(char* filename, double samp_rate, float quality) + { + return gnuradio::get_initial_sptr + (new ogg_encoder_impl(filename, samp_rate, quality)); + } + + /* + * The private constructor + */ + ogg_encoder_impl::ogg_encoder_impl(char* filename, double samp_rate, float quality) + : gr::sync_block("ogg_encoder", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(0, 0, 0)) + { + d_quality = quality; + d_out=fopen(filename,"wb"); + d_samp_rate = samp_rate; + vorbis_info_init(&d_vi); + int ret = vorbis_encode_init_vbr(&d_vi,1,d_samp_rate,d_quality); + if(ret)exit(1); + + vorbis_comment_init(&d_vc); + vorbis_comment_add_tag(&d_vc, "ENCODER", "satnogs ogg encoder"); + + vorbis_analysis_init(&d_vd, &d_vi); + vorbis_block_init(&d_vd, &d_vb); + + srand(time(NULL)); + ogg_stream_init(&d_os, rand()); + + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&d_vd, &d_vc, &header, &header_comm, &header_code); + ogg_stream_packetin(&d_os, &header); + ogg_stream_packetin(&d_os, &header_comm); + ogg_stream_packetin(&d_os, &header_code); + int result = 1; + while(result){ + result=ogg_stream_flush(&d_os,&d_og); + if(result==0)break; + fwrite(d_og.header,1,d_og.header_len,d_out); + fwrite(d_og.body,1,d_og.body_len,d_out); + } + } + + ogg_encoder_impl::~ogg_encoder_impl() + { + vorbis_analysis_wrote(&d_vd,0); + ogg_stream_clear(&d_os); + vorbis_block_clear(&d_vb); + vorbis_dsp_clear(&d_vd); + vorbis_comment_clear(&d_vc); + vorbis_info_clear(&d_vi); + fclose(d_out); + } + + int + ogg_encoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + size_t chunks = (noutput_items*sizeof(float))/2; + const signed char *in = (const signed char *) input_items[0]; + int i; + long bytes = 1024; + float **buffer=vorbis_analysis_buffer(&d_vd,chunks); + for(i=0;i + * + * 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_OGG_ENCODER_IMPL_H +#define INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H + +#include +#include + +namespace gr { + namespace satnogs { + + class ogg_encoder_impl : public ogg_encoder + { + private: + // Nothing to declare in this block. + ogg_stream_state d_os; + ogg_page d_og; + ogg_packet d_op; + + vorbis_info d_vi; + vorbis_comment d_vc; + + vorbis_dsp_state d_vd; + vorbis_block d_vb; + FILE* d_out; + double d_samp_rate; + float d_quality; + + public: + ogg_encoder_impl(char* filename, double samp_rate, float quality); + ~ogg_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_OGG_ENCODER_IMPL_H */ diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index 4c6b730..95ad4a6 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -31,6 +31,7 @@ #include "satnogs/ax25_decoder_bm.h" #include "satnogs/qb50_deframer.h" #include "satnogs/waterfall_sink.h" +#include "satnogs/ogg_enc.h" %} @@ -97,3 +98,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer); %include "satnogs/waterfall_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink); +%include "satnogs/ogg_enc.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_enc); From 11063b61f2806c376d8accf7e85a9fbe7f5d59aa Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 3 Feb 2017 01:24:10 +0200 Subject: [PATCH 18/26] Fix OGG encoder issues --- CMakeLists.txt | 1 + cmake/Modules/FindOggVorbis.cmake | 86 ++++++++++++ grc/CMakeLists.txt | 3 +- grc/satnogs_block_tree.xml | 1 + grc/satnogs_ogg_enc.xml | 38 ----- grc/satnogs_ogg_encoder.xml | 32 +++++ include/satnogs/CMakeLists.txt | 5 +- include/satnogs/{ogg_enc.h => ogg_encoder.h} | 23 ++-- lib/CMakeLists.txt | 11 +- lib/ogg_enc_impl.cc | 135 ------------------ lib/ogg_encoder_impl.cc | 137 +++++++++++++++++++ lib/{ogg_enc_impl.h => ogg_encoder_impl.h} | 41 +++--- swig/satnogs_swig.i | 6 +- 13 files changed, 303 insertions(+), 216 deletions(-) create mode 100644 cmake/Modules/FindOggVorbis.cmake delete mode 100644 grc/satnogs_ogg_enc.xml create mode 100644 grc/satnogs_ogg_encoder.xml rename include/satnogs/{ogg_enc.h => ogg_encoder.h} (72%) delete mode 100644 lib/ogg_enc_impl.cc create mode 100644 lib/ogg_encoder_impl.cc rename lib/{ogg_enc_impl.h => ogg_encoder_impl.h} (67%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c59725c..112e1f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ find_package (Threads REQUIRED) find_package(CppUnit) find_package(Doxygen) find_package(Volk REQUIRED) +find_package(OggVorbis REQUIRED) ######################################################################## # Include or not into the module blocks for debugging diff --git a/cmake/Modules/FindOggVorbis.cmake b/cmake/Modules/FindOggVorbis.cmake new file mode 100644 index 0000000..32835b0 --- /dev/null +++ b/cmake/Modules/FindOggVorbis.cmake @@ -0,0 +1,86 @@ +# - Try to find the OggVorbis libraries +# Once done this will define +# +# OGGVORBIS_FOUND - system has OggVorbis +# OGGVORBIS_VERSION - set either to 1 or 2 +# OGG_INCLUDE_DIR - the OggVorbis include directory +# VORBIS_INCLUDE_DIR - the OggVorbis include directory +# OGGVORBIS_LIBRARIES - The libraries needed to use OggVorbis +# OGG_LIBRARY - The Ogg library +# VORBIS_LIBRARY - The Vorbis library +# VORBISFILE_LIBRARY - The VorbisFile library +# VORBISENC_LIBRARY - The VorbisEnc library + +# Copyright (c) 2006, Richard Laerkaeng, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +include (CheckLibraryExists) + +find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h) +find_path(OGG_INCLUDE_DIR ogg/ogg.h) + +find_library(OGG_LIBRARY NAMES ogg) +find_library(VORBIS_LIBRARY NAMES vorbis) +find_library(VORBISFILE_LIBRARY NAMES vorbisfile) +find_library(VORBISENC_LIBRARY NAMES vorbisenc) + + +if (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + set(OGGVORBIS_FOUND TRUE) + + set(OGGVORBIS_LIBRARIES ${OGG_LIBRARY} ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBISENC_LIBRARY}) + + set(_CMAKE_REQUIRED_LIBRARIES_TMP ${CMAKE_REQUIRED_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${OGGVORBIS_LIBRARIES}) + check_library_exists(vorbis vorbis_bitrate_addblock "" HAVE_LIBVORBISENC2) + set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES_TMP}) + + if (HAVE_LIBVORBISENC2) + set (OGGVORBIS_VERSION 2) + else (HAVE_LIBVORBISENC2) + set (OGGVORBIS_VERSION 1) + endif (HAVE_LIBVORBISENC2) + +else (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + set (OGGVORBIS_VERSION) + set(OGGVORBIS_FOUND FALSE) +endif (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + + +if (OGGVORBIS_FOUND) + if (NOT OggVorbis_FIND_QUIETLY) + message(STATUS "Found OggVorbis: ${OGGVORBIS_LIBRARIES}") + endif (NOT OggVorbis_FIND_QUIETLY) +else (OGGVORBIS_FOUND) + if (OggVorbis_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find OggVorbis libraries") + endif (OggVorbis_FIND_REQUIRED) + if (NOT OggVorbis_FIND_QUITELY) + message(STATUS "Could NOT find OggVorbis libraries") + endif (NOT OggVorbis_FIND_QUITELY) +endif (OGGVORBIS_FOUND) + +#check_include_files(vorbis/vorbisfile.h HAVE_VORBISFILE_H) +#check_library_exists(ogg ogg_page_version "" HAVE_LIBOGG) +#check_library_exists(vorbis vorbis_info_init "" HAVE_LIBVORBIS) +#check_library_exists(vorbisfile ov_open "" HAVE_LIBVORBISFILE) +#check_library_exists(vorbisenc vorbis_info_clear "" HAVE_LIBVORBISENC) +#check_library_exists(vorbis vorbis_bitrate_addblock "" HAVE_LIBVORBISENC2) + +#if (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) +# message(STATUS "Ogg/Vorbis found") +# set (VORBIS_LIBS "-lvorbis -logg") +# set (VORBISFILE_LIBS "-lvorbisfile") +# set (VORBISENC_LIBS "-lvorbisenc") +# set (OGGVORBIS_FOUND TRUE) +# if (HAVE_LIBVORBISENC2) +# set (HAVE_VORBIS 2) +# else (HAVE_LIBVORBISENC2) +# set (HAVE_VORBIS 1) +# endif (HAVE_LIBVORBISENC2) +#else (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) +# message(STATUS "Ogg/Vorbis not found") +#endif (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) \ No newline at end of file diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 40d66ab..c79e908 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -31,6 +31,7 @@ list(APPEND enabled_blocks satnogs_cw_matched_filter_ff.xml satnogs_morse_decoder.xml satnogs_multi_format_msg_sink.xml + satnogs_ogg_encoder.xml satnogs_cw_to_symbol.xml satnogs_sine_matched_filter_ff.xml satnogs_udp_msg_source.xml @@ -48,5 +49,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${enabled_blocks} - satnogs_ogg_enc.xml DESTINATION share/gnuradio/grc/blocks + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index ee61c74..52f236b 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -13,6 +13,7 @@ satnogs_cw_matched_filter_ff satnogs_morse_decoder satnogs_multi_format_msg_sink + satnogs_ogg_encoder satnogs_cw_to_symbol satnogs_sine_matched_filter_ff satnogs_udp_msg_source diff --git a/grc/satnogs_ogg_enc.xml b/grc/satnogs_ogg_enc.xml deleted file mode 100644 index d5a47f5..0000000 --- a/grc/satnogs_ogg_enc.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - ogg_enc - satnogs_ogg_enc - [satnogs] - import satnogs - satnogs.ogg_enc($filename, $samp_rate, $quality) - - - ... - ... - ... - - - - - in - - - - - - out - - - diff --git a/grc/satnogs_ogg_encoder.xml b/grc/satnogs_ogg_encoder.xml new file mode 100644 index 0000000..6154ded --- /dev/null +++ b/grc/satnogs_ogg_encoder.xml @@ -0,0 +1,32 @@ + + + OGG Encoder + satnogs_ogg_encoder + import satnogs + satnogs.ogg_encoder($filename, $samp_rate, $quality) + + + File + filename + + file_save + + + + Sampling rate + samp_rate + real + + + + Quality + quality + 0.8 + real + + + + in + float + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 7f65a8a..2c16dc5 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -37,6 +37,7 @@ list(APPEND HEADER_FILES morse.h morse_decoder.h multi_format_msg_sink.h + ogg_encoder.h cw_to_symbol.h sine_matched_filter_ff.h utils.h @@ -61,6 +62,6 @@ if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND HEADER_FILES ${DEBUG_HEADER_FILES}) endif() install(FILES - ${HEADER_FILES} - ogg_enc.h DESTINATION include/satnogs + ${HEADER_FILES} + DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/ogg_enc.h b/include/satnogs/ogg_encoder.h similarity index 72% rename from include/satnogs/ogg_enc.h rename to include/satnogs/ogg_encoder.h index 45bf948..18bd62c 100644 --- a/include/satnogs/ogg_enc.h +++ b/include/satnogs/ogg_encoder.h @@ -24,28 +24,29 @@ #include #include -namespace gr { - namespace satnogs { +namespace gr +{ + namespace satnogs + { /*! - * \brief <+description of block+> + * \brief Ogg encoder and sink block * \ingroup satnogs * */ class SATNOGS_API ogg_encoder : virtual public gr::sync_block { - public: + public: typedef boost::shared_ptr sptr; /*! - * \brief Return a shared_ptr to a new instance of satnogs::ogg_encoder. - * - * To avoid accidental use of raw pointers, satnogs::ogg_encoder's - * constructor is in a private implementation - * class. satnogs::ogg_encoder::make is the public interface for - * creating new instances. + * Ogg encoder and sink block. + * @param filename filename of the output file + * @param samp_rate the sampling rate + * @param quality the quality of the output file. [0.1 - 1.0] (worst - best) */ - static sptr make(char* filename, double samp_rate, float quality); + static sptr + make (char* filename, double samp_rate, float quality); }; } // namespace satnogs diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8f7f8cd..15bcb14 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,7 +25,8 @@ include(GrPlatform) #define LIB_SUFFIX include_directories( ${Boost_INCLUDE_DIR} ${VOLK_INCLUDE_DIRS} - ${OGG_INCLUDE_DIRS} + ${VORBIS_INCLUDE_DIR} + ${OGG_INCLUDE_DIR} ) link_directories(${Boost_LIBRARY_DIRS}) @@ -41,6 +42,7 @@ list(APPEND satnogs_sources morse_tree.cc morse_decoder_impl.cc multi_format_msg_sink_impl.cc + ogg_encoder_impl.cc cw_to_symbol_impl.cc sine_matched_filter_ff_impl.cc udp_msg_source_impl.cc @@ -57,8 +59,7 @@ list(APPEND satnogs_sources ax25_encoder_mb_impl.cc ax25_decoder_bm_impl.cc qb50_deframer_impl.cc - waterfall_sink_impl.cc - ogg_enc_impl.cc ) + waterfall_sink_impl.cc) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) @@ -78,9 +79,7 @@ target_link_libraries(gnuradio-satnogs ${CMAKE_THREAD_LIBS_INIT} ${NOVA_LIBRARIES} ${VOLK_LIBRARIES} - ogg - vorbis - vorbisenc + ${OGGVORBIS_LIBRARIES} ) set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") diff --git a/lib/ogg_enc_impl.cc b/lib/ogg_enc_impl.cc deleted file mode 100644 index 8d63b73..0000000 --- a/lib/ogg_enc_impl.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- c++ -*- */ -/* - * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module - * - * Copyright (C) 2017, 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 "ogg_encoder_impl.h" - -#include -#include -#include -#include -#include - - -namespace gr { - namespace satnogs { - - ogg_encoder::sptr - ogg_encoder::make(char* filename, double samp_rate, float quality) - { - return gnuradio::get_initial_sptr - (new ogg_encoder_impl(filename, samp_rate, quality)); - } - - /* - * The private constructor - */ - ogg_encoder_impl::ogg_encoder_impl(char* filename, double samp_rate, float quality) - : gr::sync_block("ogg_encoder", - gr::io_signature::make(1, 1, sizeof(float)), - gr::io_signature::make(0, 0, 0)) - { - d_quality = quality; - d_out=fopen(filename,"wb"); - d_samp_rate = samp_rate; - vorbis_info_init(&d_vi); - int ret = vorbis_encode_init_vbr(&d_vi,1,d_samp_rate,d_quality); - if(ret)exit(1); - - vorbis_comment_init(&d_vc); - vorbis_comment_add_tag(&d_vc, "ENCODER", "satnogs ogg encoder"); - - vorbis_analysis_init(&d_vd, &d_vi); - vorbis_block_init(&d_vd, &d_vb); - - srand(time(NULL)); - ogg_stream_init(&d_os, rand()); - - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; - - vorbis_analysis_headerout(&d_vd, &d_vc, &header, &header_comm, &header_code); - ogg_stream_packetin(&d_os, &header); - ogg_stream_packetin(&d_os, &header_comm); - ogg_stream_packetin(&d_os, &header_code); - int result = 1; - while(result){ - result=ogg_stream_flush(&d_os,&d_og); - if(result==0)break; - fwrite(d_og.header,1,d_og.header_len,d_out); - fwrite(d_og.body,1,d_og.body_len,d_out); - } - } - - ogg_encoder_impl::~ogg_encoder_impl() - { - vorbis_analysis_wrote(&d_vd,0); - ogg_stream_clear(&d_os); - vorbis_block_clear(&d_vb); - vorbis_dsp_clear(&d_vd); - vorbis_comment_clear(&d_vc); - vorbis_info_clear(&d_vi); - fclose(d_out); - } - - int - ogg_encoder_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - size_t chunks = (noutput_items*sizeof(float))/2; - const signed char *in = (const signed char *) input_items[0]; - int i; - long bytes = 1024; - float **buffer=vorbis_analysis_buffer(&d_vd,chunks); - for(i=0;i + * + * 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 "ogg_encoder_impl.h" + +#include +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + ogg_encoder::sptr + ogg_encoder::make (char* filename, double samp_rate, float quality) + { + return gnuradio::get_initial_sptr ( + new ogg_encoder_impl (filename, samp_rate, quality)); + } + + /* + * The private constructor + */ + ogg_encoder_impl::ogg_encoder_impl (char* filename, double samp_rate, + float quality) : + gr::sync_block ("ogg_encoder", + gr::io_signature::make (1, 1, sizeof(float)), + gr::io_signature::make (0, 0, 0)) + { + d_quality = quality; + d_out = fopen (filename, "wb"); + d_samp_rate = samp_rate; + vorbis_info_init (&d_vi); + int ret = vorbis_encode_init_vbr (&d_vi, 1, d_samp_rate, d_quality); + if (ret) + exit (1); + + vorbis_comment_init (&d_vc); + vorbis_comment_add_tag (&d_vc, "ENCODER", "satnogs ogg encoder"); + + vorbis_analysis_init (&d_vd, &d_vi); + vorbis_block_init (&d_vd, &d_vb); + + srand (time (NULL)); + ogg_stream_init (&d_os, rand ()); + + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout (&d_vd, &d_vc, &header, &header_comm, + &header_code); + ogg_stream_packetin (&d_os, &header); + ogg_stream_packetin (&d_os, &header_comm); + ogg_stream_packetin (&d_os, &header_code); + int result = 1; + while (result) { + result = ogg_stream_flush (&d_os, &d_og); + if (result == 0) + break; + fwrite (d_og.header, 1, d_og.header_len, d_out); + fwrite (d_og.body, 1, d_og.body_len, d_out); + } + } + + ogg_encoder_impl::~ogg_encoder_impl () + { + vorbis_analysis_wrote (&d_vd, 0); + ogg_stream_clear (&d_os); + vorbis_block_clear (&d_vb); + vorbis_dsp_clear (&d_vd); + vorbis_comment_clear (&d_vc); + vorbis_info_clear (&d_vi); + fclose (d_out); + } + + int + ogg_encoder_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const char *in = (const char *) input_items[0]; + int i; + float **buffer = vorbis_analysis_buffer (&d_vd, noutput_items); + memcpy(buffer[0], in, noutput_items * sizeof(float)); + + vorbis_analysis_wrote (&d_vd, noutput_items); + + while (vorbis_analysis_blockout (&d_vd, &d_vb) == 1) { + vorbis_analysis (&d_vb, NULL); + vorbis_bitrate_addblock (&d_vb); + + while (vorbis_bitrate_flushpacket (&d_vd, &d_op)) { + + ogg_stream_packetin (&d_os, &d_op); + int result = 1; + while (result) { + int result = ogg_stream_pageout (&d_os, &d_og); + if (result == 0) + break; + fwrite (d_og.header, 1, d_og.header_len, d_out); + fwrite (d_og.body, 1, d_og.body_len, d_out); + if (ogg_page_eos (&d_og)) + result = 1; + } + } + } + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ diff --git a/lib/ogg_enc_impl.h b/lib/ogg_encoder_impl.h similarity index 67% rename from lib/ogg_enc_impl.h rename to lib/ogg_encoder_impl.h index 23e8762..c8cf28b 100644 --- a/lib/ogg_enc_impl.h +++ b/lib/ogg_encoder_impl.h @@ -18,41 +18,42 @@ * along with this program. If not, see . */ - #ifndef INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H #define INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H #include #include -namespace gr { - namespace satnogs { +namespace gr +{ + namespace satnogs + { class ogg_encoder_impl : public ogg_encoder { - private: + private: // Nothing to declare in this block. - ogg_stream_state d_os; - ogg_page d_og; - ogg_packet d_op; + ogg_stream_state d_os; + ogg_page d_og; + ogg_packet d_op; - vorbis_info d_vi; - vorbis_comment d_vc; + vorbis_info d_vi; + vorbis_comment d_vc; - vorbis_dsp_state d_vd; - vorbis_block d_vb; - FILE* d_out; - double d_samp_rate; - float d_quality; + vorbis_dsp_state d_vd; + vorbis_block d_vb; + FILE* d_out; + double d_samp_rate; + float d_quality; - public: - ogg_encoder_impl(char* filename, double samp_rate, float quality); - ~ogg_encoder_impl(); + public: + ogg_encoder_impl (char* filename, double samp_rate, float quality); + ~ogg_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); + int + work (int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace satnogs diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index 95ad4a6..8b3417a 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -31,7 +31,7 @@ #include "satnogs/ax25_decoder_bm.h" #include "satnogs/qb50_deframer.h" #include "satnogs/waterfall_sink.h" -#include "satnogs/ogg_enc.h" +#include "satnogs/ogg_encoder.h" %} @@ -98,5 +98,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer); %include "satnogs/waterfall_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink); -%include "satnogs/ogg_enc.h" -GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_enc); +%include "satnogs/ogg_encoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_encoder); From 6c8047570026cedf9ce68e49ea69a897bdb2a245 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 3 Feb 2017 16:46:12 +0200 Subject: [PATCH 19/26] Change the waterfall palette * Change the waterfall palette * OGG output file at the FM demod flowgraph --- apps/flowgraphs/fm_demod.grc | 92 ++++++++++++++--------------- apps/flowgraphs/satnogs_fm_demod.py | 8 +-- apps/scripts/satnogs_waterfall.gp | 25 ++++---- 3 files changed, 62 insertions(+), 63 deletions(-) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index 461cf59..bd06b10 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -451,53 +451,6 @@ TX sampling rate ccc - - blocks_wavfile_sink - - bits_per_sample - 16 - - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - file - file_path - - - _coordinate - (1088, 664) - - - _rotation - 0 - - - id - blocks_wavfile_sink_0 - - - nchan - 1 - - - samp_rate - audio_samp_rate - - parameter @@ -2270,6 +2223,49 @@ we shift the LO a little further rx_freq + + satnogs_ogg_encoder + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + filename + file_path + + + _coordinate + (920, 548) + + + _rotation + 180 + + + id + satnogs_ogg_encoder_0 + + + quality + 1.0 + + + samp_rate + audio_samp_rate + + satnogs_tcp_rigctl_msg_source @@ -2429,7 +2425,7 @@ we shift the LO a little further analog_quadrature_demod_cf_0 - blocks_wavfile_sink_0 + satnogs_ogg_encoder_0 0 0 diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index f97acc4..473dbfe 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,11 +5,10 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Mon Jan 23 20:10:12 2017 +# Generated: Fri Feb 3 16:44:07 2017 ################################################## from gnuradio import analog -from gnuradio import blocks from gnuradio import eng_notation from gnuradio import filter from gnuradio import gr @@ -56,6 +55,7 @@ class satnogs_fm_demod(gr.top_block): ################################################## self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 1024, waterfall_file_path, 1) self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) + self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0) self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) self.osmosdr_source_0.set_sample_rate(samp_rate_rx) @@ -71,7 +71,6 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(int(samp_rate_rx/filter_rate), (xlate_filter_taps), lo_offset, samp_rate_rx) - self.blocks_wavfile_sink_0 = blocks.wavfile_sink(file_path, 1, audio_samp_rate, 16) self.blks2_rational_resampler_xxx_1 = filter.rational_resampler_ccc( interpolation=24, decimation=125, @@ -84,7 +83,7 @@ class satnogs_fm_demod(gr.top_block): # Connections ################################################## self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) - self.connect((self.analog_quadrature_demod_cf_0, 0), (self.blocks_wavfile_sink_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0, 0), (self.satnogs_ogg_encoder_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.analog_quadrature_demod_cf_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.satnogs_waterfall_sink_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blks2_rational_resampler_xxx_1, 0)) @@ -102,7 +101,6 @@ class satnogs_fm_demod(gr.top_block): def set_file_path(self, file_path): self.file_path = file_path - self.blocks_wavfile_sink_0.open(self.file_path) def get_lo_offset(self): return self.lo_offset diff --git a/apps/scripts/satnogs_waterfall.gp b/apps/scripts/satnogs_waterfall.gp index 60dfab0..417daab 100755 --- a/apps/scripts/satnogs_waterfall.gp +++ b/apps/scripts/satnogs_waterfall.gp @@ -23,7 +23,7 @@ if (!exists("height")) height=800 if (!exists("width")) width=800 if (!exists("outfile")) outfile='/tmp/waterfall.png' -set terminal pngcairo size height,width enhanced font 'Verdana,14' +set terminal pngcairo size width,height enhanced font 'Verdana,14' set output outfile unset key @@ -36,18 +36,23 @@ set tics nomirror out scale 0.75 set xlabel 'Frequency (kHz)' set ylabel 'Time' set cbtics scale 0 +set cbtics (-110, -105, -100, -95, -90, -85, -80, -75, -70, -65, -60, -55, -50, -55, -40) # palette -set palette defined (0 '#3288BD',\ - 1 '#66C2A5',\ - 2 '#ABDDA4',\ - 3 '#E6F598',\ - 4 '#FEE08B',\ - 5 '#FDAE61',\ - 6 '#F46D43',\ - 7 '#D53E4F') +set palette defined (0 '#aa00ff',\ + 1 '#6200ea',\ + 2 '#2962ff',\ + 3 '#00b8d4',\ + 4 '#00bfa5',\ + 5 '#00c853',\ + 6 '#64dd17 ',\ + 7 '#aeea00',\ + 9 '#ffd600 ',\ + 10 '#ffab00 ',\ + 11 '#ff6d00',\ + 12 '#d50000') set ylabel 'Time (seconds)' -set cbrange [-110:-20] +set cbrange [-100:-50] set cblabel 'Power (dB)' # Get automatically the axis ranges from the file From d95b90309791e409616d579b83091aa412cd1564 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 3 Feb 2017 19:25:53 +0200 Subject: [PATCH 20/26] Fix missing break statement --- lib/udp_msg_source_impl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/udp_msg_source_impl.cc b/lib/udp_msg_source_impl.cc index 7521537..34d7a1e 100644 --- a/lib/udp_msg_source_impl.cc +++ b/lib/udp_msg_source_impl.cc @@ -112,6 +112,7 @@ namespace gr switch(d_type){ case 0: message_port_pub (pmt::mp ("msg"), pmt::make_blob (buf, bytes_num)); + break; case 1: if(bytes_num < sizeof(uint32_t)){ continue; From ae2be36bca0b32bfba77848bde7bbcdf47843721 Mon Sep 17 00:00:00 2001 From: "Fabian P. Schmidt" Date: Tue, 7 Feb 2017 12:46:06 +0100 Subject: [PATCH 21/26] Add missing requirements to installation documentation (#60) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba1f62e..570dd7a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ for decoding signals from various scientific and academic sattelites. ## Install ### Requirements -* GNU Radio ( > 3.7.2 ) +* GNU Radio ( > 3.7.7 ) * CMake ( > 3.1) * G++ (with C++11 support) * VOLK @@ -13,6 +13,7 @@ for decoding signals from various scientific and academic sattelites. *** Optional *** * gr-osmocom (for using the flowgraphs with real SDR hardware) * libnova (for building the debug blocks) +* libvorbis (for ogg vorbis encoder block) ### Installation From bf6255981e4ca05fbab1eaa8e8d7c55c1bd8a810 Mon Sep 17 00:00:00 2001 From: "Fabian P. Schmidt" Date: Tue, 7 Feb 2017 12:47:58 +0100 Subject: [PATCH 22/26] apps/scripts/satnogs_waterfall.gp: Add usage documentation (#61) --- apps/scripts/satnogs_waterfall.gp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/scripts/satnogs_waterfall.gp b/apps/scripts/satnogs_waterfall.gp index 417daab..302782f 100755 --- a/apps/scripts/satnogs_waterfall.gp +++ b/apps/scripts/satnogs_waterfall.gp @@ -16,7 +16,12 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see + +# satnogs-waterfall.gp +# Plot a waterfall diagramm from the output of the satnogs_waterfall_sink block. # +# Usage: +# gnuplot -e "inputfile='waterfall_sink.data'" -e "outfile='waterfall.png'" /usr/local/share/satnogs/scripts/satnogs_waterfall.gp reset if (!exists("height")) height=800 From 58132f9b9456a3ed1f39f7f43a37d7b70d3c19bf Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Sun, 19 Mar 2017 10:02:59 -0400 Subject: [PATCH 23/26] Expose ppm setting as parameter Allow a PPM offset to be given via command line. Defaults to 0 --- apps/flowgraphs/fm_demod.grc | 45 ++++++++++++++++++++++++++++- apps/flowgraphs/satnogs_fm_demod.py | 19 +++++++++--- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/apps/flowgraphs/fm_demod.grc b/apps/flowgraphs/fm_demod.grc index bd06b10..ef2ecb7 100644 --- a/apps/flowgraphs/fm_demod.grc +++ b/apps/flowgraphs/fm_demod.grc @@ -664,7 +664,7 @@ we shift the LO a little further corr0 - 0 + ppm freq0 @@ -2047,6 +2047,49 @@ we shift the LO a little further + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (1104, 996) + + + _rotation + 0 + + + id + ppm + + + label + + + + short_id + + + + type + intx + + + value + 0 + + parameter diff --git a/apps/flowgraphs/satnogs_fm_demod.py b/apps/flowgraphs/satnogs_fm_demod.py index 473dbfe..fa4a578 100755 --- a/apps/flowgraphs/satnogs_fm_demod.py +++ b/apps/flowgraphs/satnogs_fm_demod.py @@ -5,7 +5,7 @@ # Title: FM Generic Demodulation # Author: Manolis Surligas (surligas@gmail.com) # Description: A generic FM demodulation block -# Generated: Fri Feb 3 16:44:07 2017 +# Generated: Sun Mar 19 10:01:51 2017 ################################################## from gnuradio import analog @@ -23,7 +23,7 @@ import time class satnogs_fm_demod(gr.top_block): - def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat'): + def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, ppm=0, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat'): gr.top_block.__init__(self, "FM Generic Demodulation") ################################################## @@ -32,6 +32,7 @@ class satnogs_fm_demod(gr.top_block): self.doppler_correction_per_sec = doppler_correction_per_sec self.file_path = file_path self.lo_offset = lo_offset + self.ppm = ppm self.rigctl_port = rigctl_port self.rx_freq = rx_freq self.rx_sdr_device = rx_sdr_device @@ -60,7 +61,7 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) self.osmosdr_source_0.set_sample_rate(samp_rate_rx) self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0) - self.osmosdr_source_0.set_freq_corr(0, 0) + self.osmosdr_source_0.set_freq_corr(ppm, 0) self.osmosdr_source_0.set_dc_offset_mode(2, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) @@ -110,6 +111,13 @@ class satnogs_fm_demod(gr.top_block): self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0) self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + def get_ppm(self): + return self.ppm + + def set_ppm(self, ppm): + self.ppm = ppm + self.osmosdr_source_0.set_freq_corr(self.ppm, 0) + def get_rigctl_port(self): return self.rigctl_port @@ -203,6 +211,9 @@ def argument_parser(): parser.add_option( "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), help="Set lo_offset [default=%default]") + parser.add_option( + "", "--ppm", dest="ppm", type="intx", default=0, + help="Set ppm [default=%default]") parser.add_option( "", "--rigctl-port", dest="rigctl_port", type="intx", default=4532, help="Set rigctl_port [default=%default]") @@ -222,7 +233,7 @@ def main(top_block_cls=satnogs_fm_demod, options=None): if options is None: options, _ = argument_parser().parse_args() - tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, waterfall_file_path=options.waterfall_file_path) + tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, ppm=options.ppm, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, waterfall_file_path=options.waterfall_file_path) tb.start() tb.wait() From 5603b47cd41d4ddc65a04412ee9fbb03a61f9d59 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Sun, 19 Mar 2017 13:34:21 -0400 Subject: [PATCH 24/26] updated hw_settings.py updated the hardware settings (gain/sample rate) based on testing with and for the new fm_demod script. fixes satnogs/gr-satnogs$48 --- python/hw_settings.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/python/hw_settings.py b/python/hw_settings.py index 8ed7f94..7324dba 100644 --- a/python/hw_settings.py +++ b/python/hw_settings.py @@ -33,18 +33,18 @@ hw_tx_settings = {'usrpb200' : {'rf_gain' : 60.0, 'if_gain' : 0.0, 'bb_gain' : 20.0, 'samp_rate' : 2e6, 'antenna' : '', 'dev_arg': 'hackrf'} } -hw_rx_settings = {'usrpb200' : {'rf_gain' : 20.0, 'if_gain' : 0.0, - 'bb_gain' : 0.0, 'samp_rate' : 1e6, +hw_rx_settings = {'usrpb200' : {'rf_gain' : 50.0, 'if_gain' : 0.0, + 'bb_gain' : 0.0, 'samp_rate' : 5e5, 'antenna' : 'RX2', 'dev_arg': 'uhd'}, - 'usrp2' : {'rf_gain' : 20.0, 'if_gain' : 0.0, - 'bb_gain' : 0.0, 'samp_rate' : 2e6, + 'usrp2' : {'rf_gain' : 50.0, 'if_gain' : 0.0, + 'bb_gain' : 0.0, 'samp_rate' : 5e5, 'antenna' : 'RX2', 'dev_arg': 'uhd'}, - 'airspy' : {'rf_gain' : 16.0, 'if_gain' : 0.0, - 'bb_gain' : 0.0, 'samp_rate' : 2.5e6, + 'airspy' : {'rf_gain' : 30.0, 'if_gain' : 0.0, + 'bb_gain' : 0.0, 'samp_rate' : 10e6, 'antenna' : '', 'dev_arg': 'airspy'}, - 'hackrf' : {'rf_gain' : 0.0, 'if_gain' : 16.0, - 'bb_gain' : 20.0, 'samp_rate' : 2e6, + 'hackrf' : {'rf_gain' : 14.0, 'if_gain' : 16.0, + 'bb_gain' : 20.0, 'samp_rate' : 8e6, 'antenna' : '', 'dev_arg': 'hackrf'}, - 'rtlsdr' : {'rf_gain' : 32.0, 'if_gain' : 0.0, - 'bb_gain' : 0.0, 'samp_rate' : 2e6, + 'rtlsdr' : {'rf_gain' : 49.6, 'if_gain' : 0.0, + 'bb_gain' : 0.0, 'samp_rate' : 1.5e6, 'antenna' : '', 'dev_arg' : 'rtl'} } From c83e53f9b5a7f2d9e36c44ece77f21ad822111e8 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Thu, 23 Mar 2017 03:22:08 +0200 Subject: [PATCH 25/26] Dev (#67) * Fix UPSat QT parameters * Fix missing library versioning on CMake * Fix segfault on the rigctl message source block destruction --- CMakeLists.txt | 19 +- README.md | 6 +- .../satellites/upsat_transceiver_qt.grc | 1083 +++++++++-------- .../satellites/upsat_transceiver_qt.py | 498 ++++++++ lib/CMakeLists.txt | 31 +- lib/tcp_rigctl_msg_source_impl.cc | 4 +- 6 files changed, 1106 insertions(+), 535 deletions(-) create mode 100755 apps/flowgraphs/satellites/upsat_transceiver_qt.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 112e1f7..7f532d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,16 +29,28 @@ set (CMAKE_CXX_STANDARD 11) add_definitions(-std=c++11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") +#install to PyBOMBS target prefix if defined +if(DEFINED ENV{PYBOMBS_PREFIX}) +#IGNORE set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) + message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") +endif() + #select the release build type by default to get optimization flags if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") +#IGNORE set(CMAKE_BUILD_TYPE "Release") message(STATUS "Build type not specified: defaulting to release.") endif(NOT CMAKE_BUILD_TYPE) -set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") +#IGNORE set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") #make sure our local CMake Modules path comes first list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) +# Set the version information here +set(VERSION_INFO_MAJOR_VERSION 1) +set(VERSION_INFO_API_COMPAT 0) +set(VERSION_INFO_MINOR_VERSION 1) +set(VERSION_INFO_MAINT_VERSION git) + ######################################################################## # Compiler specific setup ######################################################################## @@ -139,7 +151,10 @@ endif() # caps such as FILTER or FFT) and change the version to the minimum # API compatible version required. set(GR_REQUIRED_COMPONENTS RUNTIME FFT) +set(GR_REQUIRED_COMPONENTS RUNTIME FILTER) find_package(Gnuradio "3.7.7" REQUIRED) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) +include(GrVersion) if(NOT CPPUNIT_FOUND) message(FATAL_ERROR "CppUnit required to compile satnogs") diff --git a/README.md b/README.md index 570dd7a..28dded6 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,13 @@ for decoding signals from various scientific and academic sattelites. * CMake ( > 3.1) * G++ (with C++11 support) * VOLK +* libogg +* libvorbis * git -*** Optional *** + +**Optional** * gr-osmocom (for using the flowgraphs with real SDR hardware) * libnova (for building the debug blocks) -* libvorbis (for ogg vorbis encoder block) ### Installation diff --git a/apps/flowgraphs/satellites/upsat_transceiver_qt.grc b/apps/flowgraphs/satellites/upsat_transceiver_qt.grc index da1f596..7e96555 100644 --- a/apps/flowgraphs/satellites/upsat_transceiver_qt.grc +++ b/apps/flowgraphs/satellites/upsat_transceiver_qt.grc @@ -1,12 +1,12 @@ - + Fri Jul 1 17:53:00 2016 options author - + Manolis Surligas (surligas@gmail.com) window_size @@ -22,7 +22,7 @@ description - + SATNOGS transceiver for UPSAT satellite _enabled @@ -30,7 +30,7 @@ _coordinate - (8, 8) + (8, 12) _rotation @@ -78,7 +78,7 @@ title - + UPSat Transceiver QT @@ -93,7 +93,7 @@ _coordinate - (544, 5) + (1048, 16) _rotation @@ -101,7 +101,7 @@ id - baud_rate + baud_rate_downlink value @@ -109,14 +109,10 @@ - variable_qtgui_range + variable comment - - - - value - 0 + FSK baud rate _enabled @@ -124,11 +120,7 @@ _coordinate - (1296, 1) - - - gui_hint - + (1048, 112) _rotation @@ -136,102 +128,11 @@ id - bb_gain_rx - - - label - BB Gain RX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider - - - - variable_qtgui_range - - comment - + baud_rate_uplink value - 0 - - - _enabled - True - - - _coordinate - (1304, 137) - - - gui_hint - - - - _rotation - 0 - - - id - bb_gain_tx - - - label - BB Gain TX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider + 1200 @@ -248,7 +149,7 @@ SDR received samples _coordinate - (664, 109) + (696, 20) _rotation @@ -275,7 +176,7 @@ SDR received samples _coordinate - (368, 5) + (840, 20) _rotation @@ -302,7 +203,34 @@ SDR received samples _coordinate - (8, 325) + (168, 932) + + + _rotation + 0 + + + id + first_stage_samp_rate_rx + + + value + samp_rate_rx / decimation_rx + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (16, 904) _rotation @@ -317,132 +245,6 @@ SDR received samples filter.firdes.gaussian(1.0, samples_per_symbol_tx, 1.0, 4*samples_per_symbol_tx) - - variable_qtgui_range - - comment - - - - value - 0 - - - _enabled - True - - - _coordinate - (1192, 1) - - - gui_hint - - - - _rotation - 0 - - - id - if_gain_rx - - - label - IF Gain RX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider - - - - variable_qtgui_range - - comment - - - - value - 0 - - - _enabled - True - - - _coordinate - (1192, 137) - - - gui_hint - - - - _rotation - 0 - - - id - if_gain_tx - - - label - IF Gain TX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider - - variable @@ -455,7 +257,7 @@ SDR received samples _coordinate - (8, 453) + (168, 1004) _rotation @@ -474,16 +276,15 @@ SDR received samples variable comment - To avoid the SDR carrier at the DC -we shift the LO a little further + _enabled - 1 + True _coordinate - (784, 5) + (296, 16) _rotation @@ -491,11 +292,11 @@ we shift the LO a little further id - lo_offset + modulation_index_downlink value - 100e3 + deviation / (baud_rate_downlink / 2.0) @@ -510,7 +311,7 @@ we shift the LO a little further _coordinate - (8, 253) + (296, 80) _rotation @@ -518,137 +319,11 @@ we shift the LO a little further id - modulation_index + modulation_index_uplink value - deviation / (baud_rate / 2.0) - - - - variable_qtgui_range - - comment - - - - value - 0 - - - _enabled - True - - - _coordinate - (1080, 1) - - - gui_hint - - - - _rotation - 0 - - - id - rf_gain_rx - - - label - RF Gain RX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 40 - - - rangeType - float - - - widget - counter_slider - - - - variable_qtgui_range - - comment - - - - value - 0 - - - _enabled - True - - - _coordinate - (1080, 137) - - - gui_hint - - - - _rotation - 0 - - - id - rf_gain_tx - - - label - RF Gain TX - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - 0 - - - step - 0.5 - - - stop - 70 - - - rangeType - float - - - widget - counter_slider + deviation / (baud_rate_uplink / 2.0) @@ -664,7 +339,7 @@ we shift the LO a little further _coordinate - (808, 109) + (1368, 16) _rotation @@ -692,7 +367,7 @@ TX sampling rate _coordinate - (528, 109) + (752, 900) _rotation @@ -704,7 +379,7 @@ TX sampling rate value - 1e6 + satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] @@ -720,7 +395,7 @@ TX sampling rate _coordinate - (248, 5) + (760, 776) _rotation @@ -732,7 +407,7 @@ TX sampling rate value - 2e6 + satnogs.hw_tx_settings[rx_sdr_device]['samp_rate'] @@ -750,7 +425,7 @@ is too great and becomes a bottlneck. _coordinate - (8, 109) + (472, 12) _rotation @@ -777,7 +452,7 @@ is too great and becomes a bottlneck. _coordinate - (8, 389) + (16, 984) _rotation @@ -812,7 +487,7 @@ is too great and becomes a bottlneck. _coordinate - (16, 762) + (16, 760) _rotation @@ -852,7 +527,7 @@ is too great and becomes a bottlneck. _coordinate - (648, 5) + (1216, 16) _rotation @@ -887,7 +562,7 @@ is too great and becomes a bottlneck. _coordinate - (1200, 308) + (792, 232) _rotation @@ -907,7 +582,7 @@ is too great and becomes a bottlneck. sensitivity - (math.pi*modulation_index) / samples_per_symbol_tx + (math.pi*modulation_index_uplink) / samples_per_symbol_tx @@ -930,7 +605,7 @@ is too great and becomes a bottlneck. _coordinate - (568, 644) + (552, 528) _rotation @@ -938,7 +613,7 @@ is too great and becomes a bottlneck. gain - ((samp_rate_rx/decimation_rx) / baud_rate)/(math.pi*modulation_index) + ((first_stage_samp_rate_rx) / baud_rate_downlink)/(math.pi*modulation_index_downlink) id @@ -981,7 +656,7 @@ is too great and becomes a bottlneck. _coordinate - (1008, 376) + (952, 272) _rotation @@ -1016,6 +691,49 @@ is too great and becomes a bottlneck. analog.GR_COS_WAVE + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (272, 756) + + + _rotation + 0 + + + id + bind_addr + + + label + + + + short_id + + + + type + string + + + value + 0.0.0.0 + + blocks_multiply_xx @@ -1036,7 +754,7 @@ is too great and becomes a bottlneck. _coordinate - (824, 464) + (832, 352) _rotation @@ -1083,7 +801,7 @@ is too great and becomes a bottlneck. _coordinate - (208, 918) + (272, 844) _rotation @@ -1130,7 +848,7 @@ is too great and becomes a bottlneck. _coordinate - (1024, 648) + (944, 528) _rotation @@ -1169,7 +887,7 @@ is too great and becomes a bottlneck. _coordinate - (776, 616) + (736, 496) _rotation @@ -1205,7 +923,7 @@ is too great and becomes a bottlneck. omega - (samp_rate_rx/decimation_rx)/baud_rate + first_stage_samp_rate_rx/baud_rate_downlink type @@ -1240,7 +958,7 @@ is too great and becomes a bottlneck. _coordinate - (304, 623) + (304, 504) _rotation @@ -1287,7 +1005,7 @@ is too great and becomes a bottlneck. _coordinate - (1472, 60) + (184, 64) _rotation @@ -1318,7 +1036,7 @@ is too great and becomes a bottlneck. _coordinate - (1480, 4) + (184, 16) _rotation @@ -1349,7 +1067,7 @@ is too great and becomes a bottlneck. _coordinate - (1480, 108) + (184, 112) _rotation @@ -1384,7 +1102,7 @@ is too great and becomes a bottlneck. _coordinate - (920, 293) + (592, 224) _rotation @@ -1419,6 +1137,50 @@ is too great and becomes a bottlneck. fff + + parameter + + alias + + + + comment + To avoid the SDR carrier at the DC +we shift the LO a little further + + + _enabled + True + + + _coordinate + (888, 772) + + + _rotation + 0 + + + id + lo_offset + + + label + + + + short_id + + + + type + eng_float + + + value + 100e3 + + osmosdr_sink @@ -1427,11 +1189,11 @@ is too great and becomes a bottlneck. ant0 - + satnogs.hw_tx_settings[tx_sdr_device]['antenna'] bb_gain0 - bb_gain_tx + satnogs.hw_tx_settings[tx_sdr_device]['bb_gain'] bw0 @@ -1447,11 +1209,11 @@ is too great and becomes a bottlneck. if_gain0 - if_gain_tx + satnogs.hw_tx_settings[tx_sdr_device]['if_gain'] gain0 - rf_gain_tx + satnogs.hw_tx_settings[tx_sdr_device]['rf_gain'] ant10 @@ -2331,7 +2093,7 @@ is too great and becomes a bottlneck. args - + satnogs.hw_tx_settings[rx_sdr_device]['dev_arg'] _enabled @@ -2339,7 +2101,7 @@ is too great and becomes a bottlneck. _coordinate - (416, 434) + (544, 312) _rotation @@ -2442,11 +2204,11 @@ is too great and becomes a bottlneck. ant0 - + satnogs.hw_rx_settings[rx_sdr_device]['antenna'] bb_gain0 - bb_gain_rx + satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'] bw0 @@ -2470,7 +2232,7 @@ is too great and becomes a bottlneck. if_gain0 - if_gain_rx + satnogs.hw_rx_settings[rx_sdr_device]['if_gain'] iq_balance_mode0 @@ -2478,7 +2240,7 @@ is too great and becomes a bottlneck. gain0 - rf_gain_rx + satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'] ant10 @@ -3730,7 +3492,7 @@ is too great and becomes a bottlneck. args - + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] _enabled @@ -3738,7 +3500,7 @@ is too great and becomes a bottlneck. _coordinate - (32, 565) + (64, 440) _rotation @@ -3861,7 +3623,7 @@ is too great and becomes a bottlneck. _coordinate - (1232, 471) + (1080, 360) _rotation @@ -3885,7 +3647,7 @@ is too great and becomes a bottlneck. rrate - samp_rate_tx / (baud_rate * samples_per_symbol_tx) + samp_rate_tx / (baud_rate_uplink * samples_per_symbol_tx) samp_delay @@ -3914,6 +3676,10 @@ is too great and becomes a bottlneck. average 1.0 + + axislabels + True + bw samp_rate_rx/decimation_rx @@ -3940,7 +3706,7 @@ is too great and becomes a bottlneck. _enabled - 0 + 1 fftsize @@ -3948,7 +3714,7 @@ is too great and becomes a bottlneck. _coordinate - (552, 722) + (312, 408) gui_hint @@ -3956,7 +3722,7 @@ is too great and becomes a bottlneck. _rotation - 0 + 180 grid @@ -4182,6 +3948,10 @@ is too great and becomes a bottlneck. wintype firdes.WIN_BLACKMAN_hARRIS + + label + Relative Gain + ymax 0 @@ -4190,9 +3960,326 @@ is too great and becomes a bottlneck. ymin -140 + + units + dB + + + + qtgui_waterfall_sink_x + + axislabels + True + + + bw + 50e3 + + + alias + + + + fc + 0 + + + comment + + + + affinity + + + + _enabled + True + + + fftsize + 1024 + + + _coordinate + (296, 628) + + + gui_hint + + + + _rotation + 180 + + + grid + False + + + id + qtgui_waterfall_sink_x_0 + + + int_max + 10 + + + int_min + -140 + + + legend + True + + + alpha1 + 1.0 + + + color1 + 0 + + + label1 + + + + alpha10 + 1.0 + + + color10 + 0 + + + label10 + + + + alpha2 + 1.0 + + + color2 + 0 + + + label2 + + + + alpha3 + 1.0 + + + color3 + 0 + + + label3 + + + + alpha4 + 1.0 + + + color4 + 0 + + + label4 + + + + alpha5 + 1.0 + + + color5 + 0 + + + label5 + + + + alpha6 + 1.0 + + + color6 + 0 + + + label6 + + + + alpha7 + 1.0 + + + color7 + 0 + + + label7 + + + + alpha8 + 1.0 + + + color8 + 0 + + + label8 + + + + alpha9 + 1.0 + + + color9 + 0 + + + label9 + + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + name + "" + + + nconnections + 1 + + + showports + True + + + freqhalf + True + + + type + complex + + + update_time + 0.10 + + + wintype + firdes.WIN_BLACKMAN_hARRIS + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (168, 756) + + + _rotation + 0 + + + id + recv_port + + + label + + + + short_id + + + + type + intx + + + value + 16886 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (648, 900) + + + _rotation + 0 + + + id + rx_sdr_device + + + label + + + + short_id + + + + type + string + + + value + usrpb200 + satnogs_ax25_decoder_bm + + n_sync_flags + 3 + alias @@ -4215,7 +4302,7 @@ is too great and becomes a bottlneck. _coordinate - (1272, 760) + (1312, 584) _rotation @@ -4250,57 +4337,6 @@ is too great and becomes a bottlneck. 0 - - satnogs_debug_msg_source - - alias - - - - comment - - - - affinity - - - - delay - 0.4 - - - _enabled - 0 - - - _coordinate - (232, 190) - - - _rotation - 0 - - - id - satnogs_debug_msg_source_0 - - - maxoutbuf - 0 - - - msg - 'HELLO UPSAT FROM EARTH' * 3 - - - minoutbuf - 0 - - - repeat - True - - satnogs_multi_format_msg_sink @@ -4317,19 +4353,19 @@ is too great and becomes a bottlneck. _enabled - 1 + True _coordinate - (1056, 916) + (1080, 560) _rotation - 0 + 180 id - satnogs_multi_format_msg_sink_0_0_0 + satnogs_multi_format_msg_sink_0 format @@ -4356,7 +4392,7 @@ is too great and becomes a bottlneck. _coordinate - (1024, 792) + (968, 624) _rotation @@ -4399,7 +4435,7 @@ is too great and becomes a bottlneck. _coordinate - (744, 862) + (728, 672) _rotation @@ -4407,7 +4443,7 @@ is too great and becomes a bottlneck. id - satnogs_udp_msg_sink_0_0_0 + satnogs_udp_msg_sink_0_0 addr @@ -4442,7 +4478,7 @@ is too great and becomes a bottlneck. _coordinate - (744, 774) + (728, 600) _rotation @@ -4450,7 +4486,7 @@ is too great and becomes a bottlneck. id - satnogs_udp_msg_sink_0_0_0_0 + satnogs_udp_msg_sink_0_0_0 addr @@ -4487,7 +4523,7 @@ similar to produce dynamic payloads. _coordinate - (240, 294) + (16, 208) _rotation @@ -4499,7 +4535,7 @@ similar to produce dynamic payloads. addr - "0.0.0.0" + bind_addr mtu @@ -4509,13 +4545,17 @@ similar to produce dynamic payloads. maxoutbuf 0 + + msg_type + 0 + minoutbuf 0 port - 16886 + recv_port @@ -4554,7 +4594,7 @@ similar to produce dynamic payloads. _coordinate - (544, 224) + (304, 152) _rotation @@ -4621,7 +4661,7 @@ similar to produce dynamic payloads. _coordinate - (24, 918) + (168, 844) _rotation @@ -4664,7 +4704,50 @@ similar to produce dynamic payloads. _coordinate - (112, 918) + (648, 776) + + + _rotation + 0 + + + id + tx_sdr_device + + + label + + + + short_id + + + + type + string + + + value + usrpb200 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (552, 780) _rotation @@ -4739,6 +4822,12 @@ similar to produce dynamic payloads. 0 0 + + freq_xlating_fir_filter_xxx_0 + qtgui_waterfall_sink_x_0 + 0 + 0 + interp_fir_filter_xxx_0 analog_frequency_modulator_fc_0 @@ -4757,39 +4846,27 @@ similar to produce dynamic payloads. 0 0 + + satnogs_ax25_decoder_bm_0 + satnogs_multi_format_msg_sink_0 + failed_pdu + in + satnogs_ax25_decoder_bm_0 satnogs_qb50_deframer_0 pdu in - - satnogs_debug_msg_source_0 - satnogs_upsat_fsk_frame_encoder_0 - msg - pdu - satnogs_qb50_deframer_0 - satnogs_multi_format_msg_sink_0_0_0 + satnogs_udp_msg_sink_0_0 out in satnogs_qb50_deframer_0 satnogs_udp_msg_sink_0_0_0 - out - in - - - satnogs_qb50_deframer_0 - satnogs_multi_format_msg_sink_0_0_0 - wod - in - - - satnogs_qb50_deframer_0 - satnogs_udp_msg_sink_0_0_0_0 wod in diff --git a/apps/flowgraphs/satellites/upsat_transceiver_qt.py b/apps/flowgraphs/satellites/upsat_transceiver_qt.py new file mode 100755 index 0000000..4a7a276 --- /dev/null +++ b/apps/flowgraphs/satellites/upsat_transceiver_qt.py @@ -0,0 +1,498 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: UPSat Transceiver QT +# Author: Manolis Surligas (surligas@gmail.com) +# Description: SATNOGS transceiver for UPSAT satellite +# Generated: Sun Feb 5 13:59:36 2017 +################################################## + +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print "Warning: failed to XInitThreads()" + +from PyQt4 import Qt +from gnuradio import analog +from gnuradio import blocks +from gnuradio import digital +from gnuradio import eng_notation +from gnuradio import filter +from gnuradio import gr +from gnuradio import qtgui +from gnuradio.eng_option import eng_option +from gnuradio.filter import firdes +from gnuradio.filter import pfb +from optparse import OptionParser +import math +import numpy +import osmosdr +import satnogs +import sip +import sys +import time + + +class upsat_transceiver_qt(gr.top_block, Qt.QWidget): + + def __init__(self, bind_addr='0.0.0.0', dest_addr='127.0.0.1', lo_offset=100e3, recv_port=16886, rx_sdr_device='usrpb200', send_port=5022, tx_sdr_device='usrpb200', wod_port=5023): + gr.top_block.__init__(self, "UPSat Transceiver QT") + Qt.QWidget.__init__(self) + self.setWindowTitle("UPSat Transceiver QT") + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + + self.settings = Qt.QSettings("GNU Radio", "upsat_transceiver_qt") + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + + ################################################## + # Parameters + ################################################## + self.bind_addr = bind_addr + self.dest_addr = dest_addr + self.lo_offset = lo_offset + self.recv_port = recv_port + self.rx_sdr_device = rx_sdr_device + self.send_port = send_port + self.tx_sdr_device = tx_sdr_device + self.wod_port = wod_port + + ################################################## + # Variables + ################################################## + self.samples_per_symbol_tx = samples_per_symbol_tx = 4*8 + self.sq_wave = sq_wave = (1.0, ) * samples_per_symbol_tx + self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate'] + self.gaussian_taps = gaussian_taps = filter.firdes.gaussian(1.0, samples_per_symbol_tx, 1.0, 4*samples_per_symbol_tx) + self.deviation = deviation = 3.9973e3 + self.decimation_rx = decimation_rx = 20 + self.baud_rate_uplink = baud_rate_uplink = 1200 + self.baud_rate_downlink = baud_rate_downlink = 9600 + self.tx_frequency = tx_frequency = 145.835e6 + + self.taps = taps = firdes.low_pass(1.0, samp_rate_rx, 20000, 60000, firdes.WIN_HAMMING, 6.76) + + self.samp_rate_tx = samp_rate_tx = satnogs.hw_tx_settings[rx_sdr_device]['samp_rate'] + self.rx_frequency = rx_frequency = 435.765e6 + self.modulation_index_uplink = modulation_index_uplink = deviation / (baud_rate_uplink / 2.0) + self.modulation_index_downlink = modulation_index_downlink = deviation / (baud_rate_downlink / 2.0) + self.interp_taps = interp_taps = numpy.convolve(numpy.array(gaussian_taps), numpy.array(sq_wave)) + self.first_stage_samp_rate_rx = first_stage_samp_rate_rx = samp_rate_rx / decimation_rx + + ################################################## + # Blocks + ################################################## + self.satnogs_upsat_fsk_frame_encoder_0 = satnogs.upsat_fsk_frame_encoder([0x33]*8 , [0x7A, 0x0E], False, False, False, True, True, 'ABCD', 0, 'ON02GR', 0, 64) + self.satnogs_udp_msg_source_0 = satnogs.udp_msg_source(bind_addr, recv_port, 1500, 0) + self.satnogs_udp_msg_sink_0_0_0 = satnogs.udp_msg_sink(dest_addr, wod_port, 1500) + self.satnogs_udp_msg_sink_0_0 = satnogs.udp_msg_sink(dest_addr, send_port, 1500) + self.satnogs_qb50_deframer_0 = satnogs.qb50_deframer(0xe) + self.satnogs_multi_format_msg_sink_0 = satnogs.multi_format_msg_sink(1) + self.satnogs_ax25_decoder_bm_0 = satnogs.ax25_decoder_bm('GND', 0, False, True, 256, 3) + self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c( + 1024, #size + firdes.WIN_BLACKMAN_hARRIS, #wintype + 0, #fc + 50e3, #bw + "", #name + 1 #number of inputs + ) + self.qtgui_waterfall_sink_x_0.set_update_time(0.10) + self.qtgui_waterfall_sink_x_0.enable_grid(False) + self.qtgui_waterfall_sink_x_0.enable_axis_labels(True) + + if not True: + self.qtgui_waterfall_sink_x_0.disable_legend() + + if "complex" == "float" or "complex" == "msg_float": + self.qtgui_waterfall_sink_x_0.set_plot_pos_half(not True) + + labels = ['', '', '', '', '', + '', '', '', '', ''] + colors = [0, 0, 0, 0, 0, + 0, 0, 0, 0, 0] + alphas = [1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0] + for i in xrange(1): + if len(labels[i]) == 0: + self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i)) + else: + self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i]) + self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i]) + self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i]) + + self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10) + + self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.pyqwidget(), Qt.QWidget) + self.top_layout.addWidget(self._qtgui_waterfall_sink_x_0_win) + self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( + 1024, #size + firdes.WIN_BLACKMAN_hARRIS, #wintype + 0, #fc + samp_rate_rx/decimation_rx, #bw + "", #name + 1 #number of inputs + ) + self.qtgui_freq_sink_x_0.set_update_time(0.01) + self.qtgui_freq_sink_x_0.set_y_axis(-140, 0) + self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') + self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") + self.qtgui_freq_sink_x_0.enable_autoscale(False) + self.qtgui_freq_sink_x_0.enable_grid(True) + self.qtgui_freq_sink_x_0.set_fft_average(1.0) + self.qtgui_freq_sink_x_0.enable_axis_labels(True) + self.qtgui_freq_sink_x_0.enable_control_panel(True) + + if not True: + self.qtgui_freq_sink_x_0.disable_legend() + + if "complex" == "float" or "complex" == "msg_float": + self.qtgui_freq_sink_x_0.set_plot_pos_half(not True) + + labels = ['', '', '', '', '', + '', '', '', '', ''] + widths = [1, 1, 1, 1, 1, + 1, 1, 1, 1, 1] + colors = ["blue", "red", "green", "black", "cyan", + "magenta", "yellow", "dark red", "dark green", "dark blue"] + alphas = [1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0] + for i in xrange(1): + if len(labels[i]) == 0: + self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i)) + else: + self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) + self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) + self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) + self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) + + self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) + self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win) + self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_ccf( + samp_rate_tx / (baud_rate_uplink * samples_per_symbol_tx), + taps=(firdes.low_pass_2(32, 32, 0.8, 0.1, 60)), + flt_size=32) + self.pfb_arb_resampler_xxx_0.declare_sample_delay(0) + + self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] ) + self.osmosdr_source_0.set_sample_rate(samp_rate_rx) + self.osmosdr_source_0.set_center_freq(rx_frequency - lo_offset, 0) + self.osmosdr_source_0.set_freq_corr(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_iq_balance_mode(0, 0) + self.osmosdr_source_0.set_gain_mode(False, 0) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0) + self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) + + self.osmosdr_sink_0 = osmosdr.sink( args="numchan=" + str(1) + " " + satnogs.hw_tx_settings[rx_sdr_device]['dev_arg'] ) + self.osmosdr_sink_0.set_sample_rate(samp_rate_tx) + self.osmosdr_sink_0.set_center_freq(tx_frequency - lo_offset, 0) + self.osmosdr_sink_0.set_freq_corr(0, 0) + self.osmosdr_sink_0.set_gain(satnogs.hw_tx_settings[tx_sdr_device]['rf_gain'], 0) + self.osmosdr_sink_0.set_if_gain(satnogs.hw_tx_settings[tx_sdr_device]['if_gain'], 0) + self.osmosdr_sink_0.set_bb_gain(satnogs.hw_tx_settings[tx_sdr_device]['bb_gain'], 0) + self.osmosdr_sink_0.set_antenna(satnogs.hw_tx_settings[tx_sdr_device]['antenna'], 0) + self.osmosdr_sink_0.set_bandwidth(samp_rate_tx, 0) + + self.interp_fir_filter_xxx_0 = filter.interp_fir_filter_fff(samples_per_symbol_tx, (interp_taps)) + self.interp_fir_filter_xxx_0.declare_sample_delay(0) + self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(decimation_rx, (taps), lo_offset, samp_rate_rx) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(first_stage_samp_rate_rx/baud_rate_downlink, 0.25*0.175*0.175, 0.5, 0.175, 0.005) + self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb() + self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate_tx, analog.GR_COS_WAVE, lo_offset , 1, 0) + self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf(((first_stage_samp_rate_rx) / baud_rate_downlink)/(math.pi*modulation_index_downlink)) + self.analog_frequency_modulator_fc_0 = analog.frequency_modulator_fc((math.pi*modulation_index_uplink) / samples_per_symbol_tx) + + ################################################## + # Connections + ################################################## + self.msg_connect((self.satnogs_ax25_decoder_bm_0, 'failed_pdu'), (self.satnogs_multi_format_msg_sink_0, 'in')) + self.msg_connect((self.satnogs_ax25_decoder_bm_0, 'pdu'), (self.satnogs_qb50_deframer_0, 'in')) + self.msg_connect((self.satnogs_qb50_deframer_0, 'out'), (self.satnogs_udp_msg_sink_0_0, 'in')) + self.msg_connect((self.satnogs_qb50_deframer_0, 'wod'), (self.satnogs_udp_msg_sink_0_0_0, 'in')) + self.msg_connect((self.satnogs_udp_msg_source_0, 'msg'), (self.satnogs_upsat_fsk_frame_encoder_0, 'pdu')) + self.connect((self.analog_frequency_modulator_fc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) + self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 1)) + self.connect((self.blocks_multiply_xx_0, 0), (self.osmosdr_sink_0, 0)) + self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0, 0)) + self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_freq_sink_x_0, 0)) + self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_waterfall_sink_x_0, 0)) + self.connect((self.interp_fir_filter_xxx_0, 0), (self.analog_frequency_modulator_fc_0, 0)) + self.connect((self.osmosdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.satnogs_upsat_fsk_frame_encoder_0, 0), (self.interp_fir_filter_xxx_0, 0)) + + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "upsat_transceiver_qt") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + + def get_bind_addr(self): + return self.bind_addr + + def set_bind_addr(self, bind_addr): + self.bind_addr = bind_addr + + def get_dest_addr(self): + return self.dest_addr + + def set_dest_addr(self, dest_addr): + self.dest_addr = dest_addr + + def get_lo_offset(self): + return self.lo_offset + + def set_lo_offset(self, lo_offset): + self.lo_offset = lo_offset + self.osmosdr_source_0.set_center_freq(self.rx_frequency - self.lo_offset, 0) + self.osmosdr_sink_0.set_center_freq(self.tx_frequency - self.lo_offset, 0) + self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset) + self.analog_sig_source_x_0.set_frequency(self.lo_offset ) + + def get_recv_port(self): + return self.recv_port + + def set_recv_port(self, recv_port): + self.recv_port = recv_port + + def get_rx_sdr_device(self): + return self.rx_sdr_device + + def set_rx_sdr_device(self, rx_sdr_device): + self.rx_sdr_device = rx_sdr_device + self.set_samp_rate_tx(satnogs.hw_tx_settings[self.rx_sdr_device]['samp_rate']) + self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate']) + self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0) + self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0) + self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0) + self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0) + + def get_send_port(self): + return self.send_port + + def set_send_port(self, send_port): + self.send_port = send_port + + def get_tx_sdr_device(self): + return self.tx_sdr_device + + def set_tx_sdr_device(self, tx_sdr_device): + self.tx_sdr_device = tx_sdr_device + self.osmosdr_sink_0.set_gain(satnogs.hw_tx_settings[self.tx_sdr_device]['rf_gain'], 0) + self.osmosdr_sink_0.set_if_gain(satnogs.hw_tx_settings[self.tx_sdr_device]['if_gain'], 0) + self.osmosdr_sink_0.set_bb_gain(satnogs.hw_tx_settings[self.tx_sdr_device]['bb_gain'], 0) + self.osmosdr_sink_0.set_antenna(satnogs.hw_tx_settings[self.tx_sdr_device]['antenna'], 0) + + def get_wod_port(self): + return self.wod_port + + def set_wod_port(self, wod_port): + self.wod_port = wod_port + + def get_samples_per_symbol_tx(self): + return self.samples_per_symbol_tx + + def set_samples_per_symbol_tx(self, samples_per_symbol_tx): + self.samples_per_symbol_tx = samples_per_symbol_tx + self.set_sq_wave((1.0, ) * self.samples_per_symbol_tx) + self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) + self.set_gaussian_taps(filter.firdes.gaussian(1.0, self.samples_per_symbol_tx, 1.0, 4*self.samples_per_symbol_tx)) + self.analog_frequency_modulator_fc_0.set_sensitivity((math.pi*self.modulation_index_uplink) / self.samples_per_symbol_tx) + + def get_sq_wave(self): + return self.sq_wave + + def set_sq_wave(self, sq_wave): + self.sq_wave = sq_wave + self.set_interp_taps(numpy.convolve(numpy.array(self.gaussian_taps), numpy.array(self.sq_wave))) + + def get_samp_rate_rx(self): + return self.samp_rate_rx + + def set_samp_rate_rx(self, samp_rate_rx): + self.samp_rate_rx = samp_rate_rx + self.set_first_stage_samp_rate_rx(self.samp_rate_rx / self.decimation_rx) + self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate_rx/self.decimation_rx) + self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx) + self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0) + + def get_gaussian_taps(self): + return self.gaussian_taps + + def set_gaussian_taps(self, gaussian_taps): + self.gaussian_taps = gaussian_taps + self.set_interp_taps(numpy.convolve(numpy.array(self.gaussian_taps), numpy.array(self.sq_wave))) + + def get_deviation(self): + return self.deviation + + def set_deviation(self, deviation): + self.deviation = deviation + self.set_modulation_index_uplink(self.deviation / (self.baud_rate_uplink / 2.0)) + self.set_modulation_index_downlink(self.deviation / (self.baud_rate_downlink / 2.0)) + + def get_decimation_rx(self): + return self.decimation_rx + + def set_decimation_rx(self, decimation_rx): + self.decimation_rx = decimation_rx + self.set_first_stage_samp_rate_rx(self.samp_rate_rx / self.decimation_rx) + self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate_rx/self.decimation_rx) + + def get_baud_rate_uplink(self): + return self.baud_rate_uplink + + def set_baud_rate_uplink(self, baud_rate_uplink): + self.baud_rate_uplink = baud_rate_uplink + self.set_modulation_index_uplink(self.deviation / (self.baud_rate_uplink / 2.0)) + self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) + + def get_baud_rate_downlink(self): + return self.baud_rate_downlink + + def set_baud_rate_downlink(self, baud_rate_downlink): + self.baud_rate_downlink = baud_rate_downlink + self.set_modulation_index_downlink(self.deviation / (self.baud_rate_downlink / 2.0)) + self.digital_clock_recovery_mm_xx_0.set_omega(self.first_stage_samp_rate_rx/self.baud_rate_downlink) + self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) + + def get_tx_frequency(self): + return self.tx_frequency + + def set_tx_frequency(self, tx_frequency): + self.tx_frequency = tx_frequency + self.osmosdr_sink_0.set_center_freq(self.tx_frequency - self.lo_offset, 0) + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.freq_xlating_fir_filter_xxx_0.set_taps((self.taps)) + + def get_samp_rate_tx(self): + return self.samp_rate_tx + + def set_samp_rate_tx(self, samp_rate_tx): + self.samp_rate_tx = samp_rate_tx + self.pfb_arb_resampler_xxx_0.set_rate(self.samp_rate_tx / (self.baud_rate_uplink * self.samples_per_symbol_tx)) + self.osmosdr_sink_0.set_sample_rate(self.samp_rate_tx) + self.osmosdr_sink_0.set_bandwidth(self.samp_rate_tx, 0) + self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate_tx) + + def get_rx_frequency(self): + return self.rx_frequency + + def set_rx_frequency(self, rx_frequency): + self.rx_frequency = rx_frequency + self.osmosdr_source_0.set_center_freq(self.rx_frequency - self.lo_offset, 0) + + def get_modulation_index_uplink(self): + return self.modulation_index_uplink + + def set_modulation_index_uplink(self, modulation_index_uplink): + self.modulation_index_uplink = modulation_index_uplink + self.analog_frequency_modulator_fc_0.set_sensitivity((math.pi*self.modulation_index_uplink) / self.samples_per_symbol_tx) + + def get_modulation_index_downlink(self): + return self.modulation_index_downlink + + def set_modulation_index_downlink(self, modulation_index_downlink): + self.modulation_index_downlink = modulation_index_downlink + self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) + + def get_interp_taps(self): + return self.interp_taps + + def set_interp_taps(self, interp_taps): + self.interp_taps = interp_taps + self.interp_fir_filter_xxx_0.set_taps((self.interp_taps)) + + def get_first_stage_samp_rate_rx(self): + return self.first_stage_samp_rate_rx + + def set_first_stage_samp_rate_rx(self, first_stage_samp_rate_rx): + self.first_stage_samp_rate_rx = first_stage_samp_rate_rx + self.digital_clock_recovery_mm_xx_0.set_omega(self.first_stage_samp_rate_rx/self.baud_rate_downlink) + self.analog_quadrature_demod_cf_0_0.set_gain(((self.first_stage_samp_rate_rx) / self.baud_rate_downlink)/(math.pi*self.modulation_index_downlink)) + + +def argument_parser(): + description = 'SATNOGS transceiver for UPSAT satellite' + parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) + parser.add_option( + "", "--bind-addr", dest="bind_addr", type="string", default='0.0.0.0', + help="Set bind_addr [default=%default]") + parser.add_option( + "", "--dest-addr", dest="dest_addr", type="string", default='127.0.0.1', + help="Set dest_addr [default=%default]") + parser.add_option( + "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3), + help="Set lo_offset [default=%default]") + parser.add_option( + "", "--recv-port", dest="recv_port", type="intx", default=16886, + help="Set recv_port [default=%default]") + parser.add_option( + "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200', + help="Set rx_sdr_device [default=%default]") + parser.add_option( + "", "--send-port", dest="send_port", type="intx", default=5022, + help="Set send_port [default=%default]") + parser.add_option( + "", "--tx-sdr-device", dest="tx_sdr_device", type="string", default='usrpb200', + help="Set tx_sdr_device [default=%default]") + parser.add_option( + "", "--wod-port", dest="wod_port", type="intx", default=5023, + help="Set wod_port [default=%default]") + return parser + + +def main(top_block_cls=upsat_transceiver_qt, options=None): + if options is None: + options, _ = argument_parser().parse_args() + + from distutils.version import StrictVersion + if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): + style = gr.prefs().get_string('qtgui', 'style', 'raster') + Qt.QApplication.setGraphicsSystem(style) + qapp = Qt.QApplication(sys.argv) + + tb = top_block_cls(bind_addr=options.bind_addr, dest_addr=options.dest_addr, lo_offset=options.lo_offset, recv_port=options.recv_port, rx_sdr_device=options.rx_sdr_device, send_port=options.send_port, tx_sdr_device=options.tx_sdr_device, wod_port=options.wod_port) + tb.start() + tb.show() + + def quitting(): + tb.stop() + tb.wait() + qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting) + qapp.exec_() + + +if __name__ == '__main__': + main() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 15bcb14..cd5e06a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -93,32 +93,11 @@ 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 -) +include(GrMiscUtils) +GR_LIBRARY_FOO(gnuradio-satnogs RUNTIME_COMPONENT "satnogs_runtime" DEVEL_COMPONENT "satnogs_devel") ######################################################################## -# Build and register unit test +# Print summary ######################################################################## -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) +message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") +message(STATUS "Building for version: ${VERSION} / ${LIBVER}") diff --git a/lib/tcp_rigctl_msg_source_impl.cc b/lib/tcp_rigctl_msg_source_impl.cc index 6368741..1680f34 100644 --- a/lib/tcp_rigctl_msg_source_impl.cc +++ b/lib/tcp_rigctl_msg_source_impl.cc @@ -71,12 +71,12 @@ namespace gr { message_port_register_out (pmt::mp ("freq")); if(d_is_server) { - boost::shared_ptr ( + d_thread = boost::shared_ptr ( new boost::thread ( boost::bind (&tcp_rigctl_msg_source_impl::rigctl_server, this))); } else{ - boost::shared_ptr ( + d_thread = boost::shared_ptr ( new boost::thread ( boost::bind (&tcp_rigctl_msg_source_impl::rigctl_client, this))); } From 165423d64cf60eacbfa995d6a766a7db3d2d8ac4 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Sat, 1 Apr 2017 16:21:15 +0300 Subject: [PATCH 26/26] Ogg source (#70) * Start Ogg source block * Add OGG audio source block The number of output streams for this block should match the number of audio streams contained inside the ogg file. If there is a mismatch an appropriate exception is thrown. --- grc/CMakeLists.txt | 2 +- grc/satnogs_block_tree.xml | 1 + grc/satnogs_ogg_source.xml | 28 ++++++++ include/satnogs/CMakeLists.txt | 2 +- include/satnogs/ogg_source.h | 59 ++++++++++++++++ lib/CMakeLists.txt | 3 +- lib/ogg_source_impl.cc | 125 +++++++++++++++++++++++++++++++++ lib/ogg_source_impl.h | 56 +++++++++++++++ swig/satnogs_swig.i | 3 + 9 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 grc/satnogs_ogg_source.xml create mode 100644 include/satnogs/ogg_source.h create mode 100644 lib/ogg_source_impl.cc create mode 100644 lib/ogg_source_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index c79e908..31275d9 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -49,5 +49,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${enabled_blocks} - DESTINATION share/gnuradio/grc/blocks + satnogs_ogg_source.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index 52f236b..bda94dd 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -14,6 +14,7 @@ satnogs_morse_decoder satnogs_multi_format_msg_sink satnogs_ogg_encoder + satnogs_ogg_source satnogs_cw_to_symbol satnogs_sine_matched_filter_ff satnogs_udp_msg_source diff --git a/grc/satnogs_ogg_source.xml b/grc/satnogs_ogg_source.xml new file mode 100644 index 0000000..9795555 --- /dev/null +++ b/grc/satnogs_ogg_source.xml @@ -0,0 +1,28 @@ + + + OGG File Source + satnogs_ogg_source + [satnogs] + import satnogs + satnogs.ogg_source($filename, $channels) + + + File + filename + + file_open + + + + Channels + channels + 1 + int + + + + out + float + $channels + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 2c16dc5..066dd1a 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -63,5 +63,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${HEADER_FILES} - DESTINATION include/satnogs + ogg_source.h DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/ogg_source.h b/include/satnogs/ogg_source.h new file mode 100644 index 0000000..18de151 --- /dev/null +++ b/include/satnogs/ogg_source.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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_OGG_SOURCE_H +#define INCLUDED_SATNOGS_OGG_SOURCE_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief OGG source block. Reads a file with an OGG audio and + * convert it to float samples + * + * \ingroup satnogs + * + */ + class SATNOGS_API ogg_source : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * + * @param filename the OGG audio file path + * @param number of channels of the OGG stream. If the actual OGG stream + * contains a different number of channels than specified an exception + * is raised + */ + static sptr + make (const std::string& filename, size_t channels = 1); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_OGG_SOURCE_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cd5e06a..a5352a5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -59,7 +59,8 @@ list(APPEND satnogs_sources ax25_encoder_mb_impl.cc ax25_decoder_bm_impl.cc qb50_deframer_impl.cc - waterfall_sink_impl.cc) + waterfall_sink_impl.cc + ogg_source_impl.cc) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) diff --git a/lib/ogg_source_impl.cc b/lib/ogg_source_impl.cc new file mode 100644 index 0000000..8292faa --- /dev/null +++ b/lib/ogg_source_impl.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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 + +#include "ogg_source_impl.h" + +#define PCM_BUF_SIZE 4096 + +namespace gr { + namespace satnogs { + + ogg_source::sptr + ogg_source::make(const std::string& filename, size_t channels) + { + return gnuradio::get_initial_sptr + (new ogg_source_impl(filename, channels)); + } + + /* + * The private constructor + */ + ogg_source_impl::ogg_source_impl (const std::string& filename, + size_t channels) : + gr::sync_block ( + "ogg_source", gr::io_signature::make (0, 0, 0), + gr::io_signature::make (channels, channels, sizeof(float))), + d_channels (channels) + { + if (channels < 1) { + throw std::invalid_argument ("At least one output channels should" + " be specified"); + } + + if (ov_fopen (filename.c_str (), &d_ogvorb_f) < 0) { + throw std::invalid_argument ("Invalid .ogg file"); + } + + vorbis_info *vi = ov_info(&d_ogvorb_f,-1); + if(vi->channels != (int) channels) { + throw std::invalid_argument ( + std::string ("Channels number specified (") + + std::to_string (channels) + + ") does not match the channels of " + "the ogg stream (" + std::to_string (vi->channels) + ")"); + } + + const int alignment_multiple = volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); + set_max_noutput_items(PCM_BUF_SIZE); + + d_in_buffer = (int16_t *)volk_malloc(PCM_BUF_SIZE * sizeof(int16_t), + volk_get_alignment()); + d_out_buffer = (float *)volk_malloc(PCM_BUF_SIZE * sizeof(float), + volk_get_alignment()); + } + + /* + * Our virtual destructor. + */ + ogg_source_impl::~ogg_source_impl() + { + ov_clear(&d_ogvorb_f); + volk_free(d_in_buffer); + volk_free(d_out_buffer); + } + + int + ogg_source_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + long int ret; + int section = 0; + int available = (noutput_items / d_channels); + int produced = 0; + + ret = ov_read (&d_ogvorb_f, (char *)d_in_buffer, + available * sizeof(int16_t), + 0, sizeof(int16_t), 1, §ion); + if(ret < sizeof(int16_t)) { + return WORK_DONE; + } + + /* Convert to float the signed-short audio samples */ + volk_16i_s32f_convert_32f (d_out_buffer, d_in_buffer, 2 << 15, + ret / sizeof(int16_t)); + + /* De-interleave the available channels */ + for(int i = 0; i < ret / sizeof(int16_t); i += d_channels, produced++) { + for(int chan = 0; chan < d_channels; chan++){ + ((float *)output_items[chan])[produced] = d_out_buffer[i * d_channels + chan]; + } + } + + return produced; + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/ogg_source_impl.h b/lib/ogg_source_impl.h new file mode 100644 index 0000000..3a73f4a --- /dev/null +++ b/lib/ogg_source_impl.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, 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_OGG_SOURCE_IMPL_H +#define INCLUDED_SATNOGS_OGG_SOURCE_IMPL_H + +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + class ogg_source_impl : public ogg_source + { + private: + const size_t d_channels; + OggVorbis_File d_ogvorb_f; + + int16_t *d_in_buffer; + float *d_out_buffer; + + public: + ogg_source_impl (const std::string& filename, size_t channels); + ~ogg_source_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_OGG_SOURCE_IMPL_H */ + diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index 8b3417a..bc54368 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -32,6 +32,7 @@ #include "satnogs/qb50_deframer.h" #include "satnogs/waterfall_sink.h" #include "satnogs/ogg_encoder.h" +#include "satnogs/ogg_source.h" %} @@ -100,3 +101,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer); GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink); %include "satnogs/ogg_encoder.h" GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_encoder); +%include "satnogs/ogg_source.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_source);