├── .gitignore ├── CMakeLists.txt ├── apps ├── CMakeLists.txt └── ais_rx.py ├── cmake └── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── FindGnuradioCore.cmake │ ├── FindGruel.cmake │ ├── GrMiscUtils.cmake │ ├── GrPlatform.cmake │ ├── GrPython.cmake │ ├── GrSwig.cmake │ └── GrTest.cmake ├── docs ├── CMakeLists.txt └── doxygen │ ├── CMakeLists.txt │ ├── Doxyfile.in │ ├── Doxyfile.swig_doc.in │ ├── doxyxml │ ├── .gitignore │ ├── Makefile.am │ ├── __init__.py │ ├── base.py │ ├── doxyindex.py │ ├── example │ │ ├── Doxyfile │ │ ├── aadvark.cc │ │ ├── aadvark.h │ │ └── xml │ │ │ ├── aadvark_8cc.xml │ │ │ ├── aadvark_8h.xml │ │ │ ├── classAadvark.xml │ │ │ ├── combine.xslt │ │ │ ├── compound.xsd │ │ │ ├── index.xml │ │ │ └── index.xsd │ ├── generated │ │ ├── __init__.py │ │ ├── compound.py │ │ ├── compoundsuper.py │ │ ├── index.py │ │ └── indexsuper.py │ ├── run_tests.in │ └── text.py │ ├── other │ ├── group_defs.dox │ └── main_page.dox │ └── swig_doc.py ├── grc └── CMakeLists.txt ├── include ├── CMakeLists.txt ├── ais_extended_lms_dfe_ff.h ├── ais_freqest.h ├── ais_invert.h ├── ais_parse.h ├── ais_unstuff.h └── gr_ais_api.h ├── lib ├── CMakeLists.txt ├── ais_extended_lms_dfe_ff.cc ├── ais_freqest.cc ├── ais_invert.cc ├── ais_parse.cc └── ais_unstuff.cc ├── python ├── CMakeLists.txt ├── __init__.py ├── ais_demod.py ├── fsm_utils.py └── gmsk_sync.py └── swig ├── CMakeLists.txt └── gr_ais_swig.i /.gitignore: -------------------------------------------------------------------------------- 1 | /*.cache 2 | /*.la 3 | /*.lo 4 | /*.pc 5 | /.deps 6 | /.la 7 | /.libs 8 | /.lo 9 | /Makefile 10 | /Makefile.in 11 | /aclocal.m4 12 | /autom4te.cache 13 | /config.cache 14 | /config.h 15 | /config.h.in 16 | /config.log 17 | /config.status 18 | /configure 19 | /depcomp 20 | /install-sh 21 | /libtool 22 | /ltmain.sh 23 | /make.log 24 | /missing 25 | /missing 26 | /mkinstalldirs 27 | /py-compile 28 | /stamp-h 29 | /stamp-h.in 30 | /stamp-h1 31 | /stamp-h1.in 32 | /stamp-h2.in 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | 21 | ######################################################################## 22 | # Project setup 23 | ######################################################################## 24 | cmake_minimum_required(VERSION 2.6) 25 | project(gr-gr_ais CXX) 26 | enable_testing() 27 | 28 | #select the release build type by default to get optimization flags 29 | if(NOT CMAKE_BUILD_TYPE) 30 | set(CMAKE_BUILD_TYPE "Release") 31 | message(STATUS "Build type not specified: defaulting to release.") 32 | endif(NOT CMAKE_BUILD_TYPE) 33 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") 34 | 35 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) 36 | 37 | ######################################################################## 38 | # Compiler specific setup 39 | ######################################################################## 40 | if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) 41 | #http://gcc.gnu.org/wiki/Visibility 42 | add_definitions(-fvisibility=hidden) 43 | endif() 44 | 45 | ######################################################################## 46 | # Find boost 47 | ######################################################################## 48 | if(UNIX AND EXISTS "/usr/lib64") 49 | list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix 50 | endif(UNIX AND EXISTS "/usr/lib64") 51 | set(Boost_ADDITIONAL_VERSIONS 52 | "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" 53 | "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" 54 | "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" 55 | "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" 56 | "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" 57 | "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" 58 | "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" 59 | ) 60 | find_package(Boost "1.35") 61 | 62 | if(NOT Boost_FOUND) 63 | message(FATAL_ERROR "Boost required to compile gr_ais") 64 | endif() 65 | 66 | ######################################################################## 67 | # Install directories 68 | ######################################################################## 69 | include(GrPlatform) #define LIB_SUFFIX 70 | set(GR_RUNTIME_DIR bin) 71 | set(GR_LIBRARY_DIR lib${LIB_SUFFIX}) 72 | set(GR_INCLUDE_DIR include) 73 | set(GR_DATA_DIR share) 74 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 75 | set(GR_DOC_DIR ${GR_DATA_DIR}/doc) 76 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 77 | set(GR_CONF_DIR etc) 78 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 79 | set(GR_LIBEXEC_DIR libexec) 80 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 81 | set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks) 82 | 83 | ######################################################################## 84 | # Find gnuradio build dependencies 85 | ######################################################################## 86 | find_package(Gruel) 87 | find_package(GnuradioCore) 88 | 89 | if(NOT GRUEL_FOUND) 90 | message(FATAL_ERROR "Gruel required to compile gr_ais") 91 | endif() 92 | 93 | if(NOT GNURADIO_CORE_FOUND) 94 | message(FATAL_ERROR "GnuRadio Core required to compile gr_ais") 95 | endif() 96 | 97 | ######################################################################## 98 | # Setup the include and linker paths 99 | ######################################################################## 100 | include_directories( 101 | ${CMAKE_SOURCE_DIR}/include 102 | ${Boost_INCLUDE_DIRS} 103 | ${GRUEL_INCLUDE_DIRS} 104 | ${GNURADIO_CORE_INCLUDE_DIRS} 105 | ) 106 | 107 | link_directories( 108 | ${Boost_LIBRARY_DIRS} 109 | ${GRUEL_LIBRARY_DIRS} 110 | ${GNURADIO_CORE_LIBRARY_DIRS} 111 | ) 112 | 113 | # Set component parameters 114 | set(GR_GR_AIS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE) 115 | set(GR_GR_AIS_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE) 116 | 117 | ######################################################################## 118 | # Add subdirectories 119 | ######################################################################## 120 | add_subdirectory(include) 121 | add_subdirectory(lib) 122 | add_subdirectory(swig) 123 | add_subdirectory(python) 124 | add_subdirectory(grc) 125 | add_subdirectory(apps) 126 | add_subdirectory(docs) -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | include(GrPython) 21 | 22 | GR_PYTHON_INSTALL( 23 | PROGRAMS 24 | ais_rx.py 25 | DESTINATION bin 26 | ) 27 | -------------------------------------------------------------------------------- /apps/ais_rx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #ais decoder, main app 3 | #uses demod_pkt to register a callback 4 | 5 | #DONE: AIS freqs are fixed. Allow the user to set an error offset, and then monitor BOTH ais freqs, 161.975 and 162.025. 6 | #something else to do: brute-force error correction, a la gr-air. 7 | #another thing to do: use a Viterbi algorithm for detecting the demodulated data 8 | 9 | from gnuradio import gr, gru, blks2, optfir 10 | from gnuradio import eng_notation 11 | from gr_ais import * 12 | from gr_ais.ais_demod import * 13 | from gnuradio import digital 14 | #from ais_parser import * 15 | from optparse import OptionParser 16 | from gnuradio.eng_option import eng_option 17 | 18 | #from pkt import * 19 | import time 20 | import sys 21 | import gnuradio.gr.gr_threading as _threading 22 | import socket 23 | 24 | class top_block_runner(_threading.Thread): 25 | def __init__(self, tb): 26 | _threading.Thread.__init__(self) 27 | self.setDaemon(1) 28 | self.tb = tb 29 | self.done = False 30 | self.start() 31 | 32 | def run(self): 33 | self.tb.run() 34 | self.done = True 35 | 36 | class my_top_block(gr.top_block): 37 | def __init__(self, options, queue): 38 | gr.top_block.__init__(self) 39 | 40 | if options.filename is not None: 41 | self.u = gr.file_source(gr.sizeof_gr_complex, options.filename) 42 | elif options.rtlsdr: 43 | import osmosdr 44 | self.u = osmosdr.source_c(options.args) 45 | self.u.set_sample_rate(options.rate) 46 | self.u.set_freq_corr(options.error) 47 | if not self.u.set_center_freq(162.0e6): 48 | print "Failed to set frequency" 49 | self.u.set_gain_mode(0) 50 | if options.gain is None: 51 | options.gain = 49 52 | self.u.set_gain(options.gain) 53 | else: 54 | from gnuradio import uhd 55 | self.u = uhd.usrp_source(options.addr, 56 | io_type=uhd.io_type.COMPLEX_FLOAT32, 57 | num_channels=1) 58 | 59 | if options.subdev is not None: 60 | self.u.set_subdev_spec(options.subdev, 0) 61 | self.u.set_samp_rate(options.rate) 62 | 63 | self._freq_offset = options.error 64 | #print "Frequency offset is %i" % self._freq_offset 65 | self._actual_freq = 162.0e6 - self._freq_offset #tune between the two AIS freqs 66 | #print "Tuning to: %fMHz" % float(self._actual_freq / 1e6) 67 | if not(self.tune(self._actual_freq)): 68 | print "Failed to set initial frequency" 69 | 70 | if options.gain is None: #set to halfway 71 | g = self.u.get_gain_range() 72 | options.gain = (g.start()+g.stop()) / 2.0 73 | 74 | #print "Setting gain to %i" % options.gain 75 | self.u.set_gain(options.gain) 76 | 77 | 78 | #here we're setting up TWO receivers, designated A and B. A is on 161.975, B is on 162.025. they both output data to the queue. 79 | self.ais_rx(self.u, 161.975e6 - 162.0e6, "A", options, queue); 80 | self.ais_rx(self.u, 162.025e6 - 162.0e6, "B", options, queue); 81 | 82 | 83 | def tune(self, freq): 84 | result = self.u.set_center_freq(freq) 85 | return True 86 | 87 | return False 88 | 89 | def ais_rx(self, src, freq, designator, options, queue): 90 | self.rate = options.rate 91 | self.u = src 92 | self.coeffs = gr.firdes.low_pass(1,self.rate,7000,1000) 93 | self._filter_decimation = int(self.rate / 64.0e3) 94 | print "%s: Sampling @ %f, decim @ %d" % (designator, self.rate, self._filter_decimation) 95 | self.filter = gr.freq_xlating_fir_filter_ccf(self._filter_decimation, 96 | self.coeffs, 97 | freq, 98 | self.rate) 99 | 100 | self._bits_per_sec = 9600.0; 101 | 102 | self._samples_per_symbol = self.rate / self._filter_decimation / self._bits_per_sec 103 | 104 | options.samples_per_symbol = self._samples_per_symbol 105 | options.gain_mu = 0.3 106 | options.mu=0.5 107 | options.omega_relative_limit = 0.0001 108 | options.bits_per_sec = self._bits_per_sec 109 | options.fftlen = 4096 #trades off accuracy of freq estimation in presence of noise, vs. delay time. 110 | options.samp_rate = self.rate / self._filter_decimation 111 | self.demod = ais_demod(options) #ais_demod.py, hierarchical demodulation block, takes in complex baseband and spits out 1-bit packed bitstream 112 | self.unstuff = ais.unstuff() #ais_unstuff.cc, unstuffs data 113 | self.start_correlator = gr.correlate_access_code_tag_bb("1010101010101010", 0, "ais_preamble") #should mark start of packet 114 | self.stop_correlator = gr.correlate_access_code_tag_bb("01111110", 0, "ais_frame") #should mark start and end of packet 115 | self.parse = ais.parse(queue, designator) #ais_parse.cc, calculates CRC, parses data into ASCII message, moves data onto queue 116 | 117 | self.connect(self.u, 118 | self.filter, 119 | self.demod, 120 | self.unstuff, 121 | self.start_correlator, 122 | self.stop_correlator, 123 | self.parse) #parse posts messages to the queue, which the main loop reads and prints 124 | 125 | 126 | def main(): 127 | # Create Options Parser: 128 | parser = OptionParser (option_class=eng_option, conflict_handler="resolve") 129 | expert_grp = parser.add_option_group("Expert") 130 | 131 | parser.add_option("-a", "--addr", type="string", 132 | help="UHD source address", default="") 133 | parser.add_option("-s", "--subdev", type="string", 134 | help="UHD subdev spec", default=None) 135 | parser.add_option("-A", "--antenna", type="string", default=None, 136 | help="select Rx Antenna where appropriate") 137 | # parser.add_option("-f", "--freq", type="eng_float", default=161.975e6, 138 | # help="set receive frequency to MHz [default=%default]", metavar="FREQ") 139 | parser.add_option("-e", "--error", type="eng_float", default=0, 140 | help="set offset error of USRP [default=%default]") 141 | parser.add_option("-g", "--gain", type="int", default=None, 142 | help="set RF gain", metavar="dB") 143 | parser.add_option("-r", "--rate", type="eng_float", default=256e3, 144 | help="set fgpa decimation rate to DECIM [default=%default]") 145 | parser.add_option("-F", "--filename", type="string", default=None, 146 | help="read data from file instead of USRP") 147 | parser.add_option("-v", "--viterbi", action="store_true", default=False, 148 | help="Use optional coherent demodulation and Viterbi decoder") 149 | parser.add_option("-t", "--tcp", action="store_true", default=False, 150 | help="Start a TCP server on port 9987 instead of outputting to stdout. Useful for gpsd.") 151 | parser.add_option("-d", "--rtlsdr", action="store_true", default=False, 152 | help="Use RTL-SDR dongle") 153 | parser.add_option("-D", "--args", type="string", default="", 154 | help="arguments to pass to UHD/RTL constructor") 155 | 156 | 157 | (options, args) = parser.parse_args () 158 | 159 | if len(args) != 0: 160 | parser.print_help(sys.stderr) 161 | sys.exit(1) 162 | 163 | # build the graph 164 | queue = gr.msg_queue() 165 | tb = my_top_block(options, queue) 166 | runner = top_block_runner(tb) 167 | 168 | conns = [] #active connections 169 | if options.tcp is True: 170 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 171 | s.bind(('', 9987)) 172 | s.listen(1) 173 | s.setblocking(0) 174 | 175 | try: 176 | while 1: 177 | if options.tcp is True: 178 | try: 179 | conn, addr = s.accept() 180 | conns.append(conn) 181 | print "Connections: ", len(conns) 182 | except socket.error: 183 | pass 184 | 185 | if not queue.empty_p(): 186 | while not queue.empty_p(): 187 | msg = queue.delete_head() # Blocking read 188 | sentence = msg.to_string() 189 | if options.tcp is True: 190 | for conn in conns[:]: 191 | try: 192 | conn.send(sentence + "\n") 193 | except socket.error: 194 | conns.remove(conn) 195 | print "Connections: ", len(conns) 196 | else: 197 | print sentence 198 | sys.stdout.flush() 199 | 200 | elif runner.done: 201 | if options.tcp is True: 202 | s.close() 203 | break 204 | else: 205 | time.sleep(0.1) 206 | 207 | except KeyboardInterrupt: 208 | tb.stop() 209 | runner = None 210 | 211 | if __name__ == '__main__': 212 | main() 213 | 214 | 215 | -------------------------------------------------------------------------------- /cmake/Modules/CMakeParseArgumentsCopy.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE_PARSE_ARGUMENTS( args...) 2 | # 3 | # CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for 4 | # parsing the arguments given to that macro or function. 5 | # It processes the arguments and defines a set of variables which hold the 6 | # values of the respective options. 7 | # 8 | # The argument contains all options for the respective macro, 9 | # i.e. keywords which can be used when calling the macro without any value 10 | # following, like e.g. the OPTIONAL keyword of the install() command. 11 | # 12 | # The argument contains all keywords for this macro 13 | # which are followed by one value, like e.g. DESTINATION keyword of the 14 | # install() command. 15 | # 16 | # The argument contains all keywords for this macro 17 | # which can be followed by more than one value, like e.g. the TARGETS or 18 | # FILES keywords of the install() command. 19 | # 20 | # When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the 21 | # keywords listed in , and 22 | # a variable composed of the given 23 | # followed by "_" and the name of the respective keyword. 24 | # These variables will then hold the respective value from the argument list. 25 | # For the keywords this will be TRUE or FALSE. 26 | # 27 | # All remaining arguments are collected in a variable 28 | # _UNPARSED_ARGUMENTS, this can be checked afterwards to see whether 29 | # your macro was called with unrecognized parameters. 30 | # 31 | # As an example here a my_install() macro, which takes similar arguments as the 32 | # real install() command: 33 | # 34 | # function(MY_INSTALL) 35 | # set(options OPTIONAL FAST) 36 | # set(oneValueArgs DESTINATION RENAME) 37 | # set(multiValueArgs TARGETS CONFIGURATIONS) 38 | # cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) 39 | # ... 40 | # 41 | # Assume my_install() has been called like this: 42 | # my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) 43 | # 44 | # After the cmake_parse_arguments() call the macro will have set the following 45 | # variables: 46 | # MY_INSTALL_OPTIONAL = TRUE 47 | # MY_INSTALL_FAST = FALSE (this option was not used when calling my_install() 48 | # MY_INSTALL_DESTINATION = "bin" 49 | # MY_INSTALL_RENAME = "" (was not used) 50 | # MY_INSTALL_TARGETS = "foo;bar" 51 | # MY_INSTALL_CONFIGURATIONS = "" (was not used) 52 | # MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" 53 | # 54 | # You can the continue and process these variables. 55 | # 56 | # Keywords terminate lists of values, e.g. if directly after a one_value_keyword 57 | # another recognized keyword follows, this is interpreted as the beginning of 58 | # the new option. 59 | # E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in 60 | # MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would 61 | # be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. 62 | 63 | #============================================================================= 64 | # Copyright 2010 Alexander Neundorf 65 | # 66 | # Distributed under the OSI-approved BSD License (the "License"); 67 | # see accompanying file Copyright.txt for details. 68 | # 69 | # This software is distributed WITHOUT ANY WARRANTY; without even the 70 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 71 | # See the License for more information. 72 | #============================================================================= 73 | # (To distribute this file outside of CMake, substitute the full 74 | # License text for the above reference.) 75 | 76 | 77 | if(__CMAKE_PARSE_ARGUMENTS_INCLUDED) 78 | return() 79 | endif() 80 | set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE) 81 | 82 | 83 | function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames) 84 | # first set all result variables to empty/FALSE 85 | foreach(arg_name ${_singleArgNames} ${_multiArgNames}) 86 | set(${prefix}_${arg_name}) 87 | endforeach(arg_name) 88 | 89 | foreach(option ${_optionNames}) 90 | set(${prefix}_${option} FALSE) 91 | endforeach(option) 92 | 93 | set(${prefix}_UNPARSED_ARGUMENTS) 94 | 95 | set(insideValues FALSE) 96 | set(currentArgName) 97 | 98 | # now iterate over all arguments and fill the result variables 99 | foreach(currentArg ${ARGN}) 100 | list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword 101 | list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword 102 | list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword 103 | 104 | if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1) 105 | if(insideValues) 106 | if("${insideValues}" STREQUAL "SINGLE") 107 | set(${prefix}_${currentArgName} ${currentArg}) 108 | set(insideValues FALSE) 109 | elseif("${insideValues}" STREQUAL "MULTI") 110 | list(APPEND ${prefix}_${currentArgName} ${currentArg}) 111 | endif() 112 | else(insideValues) 113 | list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) 114 | endif(insideValues) 115 | else() 116 | if(NOT ${optionIndex} EQUAL -1) 117 | set(${prefix}_${currentArg} TRUE) 118 | set(insideValues FALSE) 119 | elseif(NOT ${singleArgIndex} EQUAL -1) 120 | set(currentArgName ${currentArg}) 121 | set(${prefix}_${currentArgName}) 122 | set(insideValues "SINGLE") 123 | elseif(NOT ${multiArgIndex} EQUAL -1) 124 | set(currentArgName ${currentArg}) 125 | set(${prefix}_${currentArgName}) 126 | set(insideValues "MULTI") 127 | endif() 128 | endif() 129 | 130 | endforeach(currentArg) 131 | 132 | # propagate the result variables to the caller: 133 | foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) 134 | set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) 135 | endforeach(arg_name) 136 | set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) 137 | 138 | endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs) 139 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioCore.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_CORE gnuradio-core QUIET) 3 | 4 | FIND_PATH( 5 | GNURADIO_CORE_INCLUDE_DIRS 6 | NAMES gr_random.h 7 | HINTS $ENV{GNURADIO_CORE_DIR}/include/gnuradio 8 | ${PC_GNURADIO_CORE_INCLUDE_DIR} 9 | PATHS /usr/local/include/gnuradio 10 | /usr/include/gnuradio 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GNURADIO_CORE_LIBRARIES 15 | NAMES gnuradio-core 16 | HINTS $ENV{GNURADIO_CORE_DIR}/lib 17 | ${PC_GNURADIO_CORE_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/local/lib64 20 | /usr/lib 21 | /usr/lib64 22 | ) 23 | 24 | INCLUDE(FindPackageHandleStandardArgs) 25 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_CORE DEFAULT_MSG GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS) 26 | MARK_AS_ADVANCED(GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS) 27 | -------------------------------------------------------------------------------- /cmake/Modules/FindGruel.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GRUEL gnuradio-core QUIET) 3 | 4 | FIND_PATH( 5 | GRUEL_INCLUDE_DIRS 6 | NAMES gruel/attributes.h 7 | HINTS $ENV{GRUEL_DIR}/include 8 | ${PC_GRUEL_INCLUDE_DIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GRUEL_LIBRARIES 15 | NAMES gruel 16 | HINTS $ENV{GRUEL_DIR}/lib 17 | ${PC_GRUEL_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/local/lib64 20 | /usr/lib 21 | /usr/lib64 22 | ) 23 | 24 | INCLUDE(FindPackageHandleStandardArgs) 25 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GRUEL DEFAULT_MSG GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS) 26 | MARK_AS_ADVANCED(GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS) 27 | -------------------------------------------------------------------------------- /cmake/Modules/GrMiscUtils.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2010-2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | if(DEFINED __INCLUDED_GR_MISC_UTILS_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_MISC_UTILS_CMAKE TRUE) 24 | 25 | ######################################################################## 26 | # Set global variable macro. 27 | # Used for subdirectories to export settings. 28 | # Example: include and library paths. 29 | ######################################################################## 30 | function(GR_SET_GLOBAL var) 31 | set(${var} ${ARGN} CACHE INTERNAL "" FORCE) 32 | endfunction(GR_SET_GLOBAL) 33 | 34 | ######################################################################## 35 | # Set the pre-processor definition if the condition is true. 36 | # - def the pre-processor definition to set and condition name 37 | ######################################################################## 38 | function(GR_ADD_COND_DEF def) 39 | if(${def}) 40 | add_definitions(-D${def}) 41 | endif(${def}) 42 | endfunction(GR_ADD_COND_DEF) 43 | 44 | ######################################################################## 45 | # Check for a header and conditionally set a compile define. 46 | # - hdr the relative path to the header file 47 | # - def the pre-processor definition to set 48 | ######################################################################## 49 | function(GR_CHECK_HDR_N_DEF hdr def) 50 | include(CheckIncludeFileCXX) 51 | CHECK_INCLUDE_FILE_CXX(${hdr} ${def}) 52 | GR_ADD_COND_DEF(${def}) 53 | endfunction(GR_CHECK_HDR_N_DEF) 54 | 55 | ######################################################################## 56 | # Include subdirectory macro. 57 | # Sets the CMake directory variables, 58 | # includes the subdirectory CMakeLists.txt, 59 | # resets the CMake directory variables. 60 | # 61 | # This macro includes subdirectories rather than adding them 62 | # so that the subdirectory can affect variables in the level above. 63 | # This provides a work-around for the lack of convenience libraries. 64 | # This way a subdirectory can append to the list of library sources. 65 | ######################################################################## 66 | macro(GR_INCLUDE_SUBDIRECTORY subdir) 67 | #insert the current directories on the front of the list 68 | list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR}) 69 | list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR}) 70 | 71 | #set the current directories to the names of the subdirs 72 | set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}) 73 | set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir}) 74 | 75 | #include the subdirectory CMakeLists to run it 76 | file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 77 | include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) 78 | 79 | #reset the value of the current directories 80 | list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR) 81 | list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR) 82 | 83 | #pop the subdir names of the front of the list 84 | list(REMOVE_AT _cmake_source_dirs 0) 85 | list(REMOVE_AT _cmake_binary_dirs 0) 86 | endmacro(GR_INCLUDE_SUBDIRECTORY) 87 | 88 | ######################################################################## 89 | # Check if a compiler flag works and conditionally set a compile define. 90 | # - flag the compiler flag to check for 91 | # - have the variable to set with result 92 | ######################################################################## 93 | macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have) 94 | include(CheckCXXCompilerFlag) 95 | CHECK_CXX_COMPILER_FLAG(${flag} ${have}) 96 | if(${have}) 97 | add_definitions(${flag}) 98 | endif(${have}) 99 | endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) 100 | 101 | ######################################################################## 102 | # Generates the .la libtool file 103 | # This appears to generate libtool files that cannot be used by auto*. 104 | # Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest]) 105 | # Notice: there is not COMPONENT option, these will not get distributed. 106 | ######################################################################## 107 | function(GR_LIBTOOL) 108 | if(NOT DEFINED GENERATE_LIBTOOL) 109 | set(GENERATE_LIBTOOL OFF) #disabled by default 110 | endif() 111 | 112 | if(GENERATE_LIBTOOL) 113 | include(CMakeParseArgumentsCopy) 114 | CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN}) 115 | 116 | find_program(LIBTOOL libtool) 117 | if(LIBTOOL) 118 | include(CMakeMacroLibtoolFile) 119 | CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION}) 120 | endif(LIBTOOL) 121 | endif(GENERATE_LIBTOOL) 122 | 123 | endfunction(GR_LIBTOOL) 124 | 125 | ######################################################################## 126 | # Do standard things to the library target 127 | # - set target properties 128 | # - make install rules 129 | # Also handle gnuradio custom naming conventions w/ extras mode. 130 | ######################################################################## 131 | function(GR_LIBRARY_FOO target) 132 | #parse the arguments for component names 133 | include(CMakeParseArgumentsCopy) 134 | CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN}) 135 | 136 | #set additional target properties 137 | set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER}) 138 | 139 | #install the generated files like so... 140 | install(TARGETS ${target} 141 | LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file 142 | ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file 143 | RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file 144 | ) 145 | 146 | #extras mode enabled automatically on linux 147 | if(NOT DEFINED LIBRARY_EXTRAS) 148 | set(LIBRARY_EXTRAS ${LINUX}) 149 | endif() 150 | 151 | #special extras mode to enable alternative naming conventions 152 | if(LIBRARY_EXTRAS) 153 | 154 | #create .la file before changing props 155 | GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR}) 156 | 157 | #give the library a special name with ultra-zero soversion 158 | set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0") 159 | set(target_name lib${target}-${LIBVER}.so.0.0.0) 160 | 161 | #custom command to generate symlinks 162 | add_custom_command( 163 | TARGET ${target} 164 | POST_BUILD 165 | COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so 166 | COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 167 | COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install 168 | ) 169 | 170 | #and install the extra symlinks 171 | install( 172 | FILES 173 | ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so 174 | ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 175 | DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} 176 | ) 177 | 178 | endif(LIBRARY_EXTRAS) 179 | endfunction(GR_LIBRARY_FOO) 180 | 181 | ######################################################################## 182 | # Create a dummy custom command that depends on other targets. 183 | # Usage: 184 | # GR_GEN_TARGET_DEPS(unique_name target_deps ...) 185 | # ADD_CUSTOM_COMMAND( ${target_deps}) 186 | # 187 | # Custom command cant depend on targets, but can depend on executables, 188 | # and executables can depend on targets. So this is the process: 189 | ######################################################################## 190 | function(GR_GEN_TARGET_DEPS name var) 191 | file( 192 | WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in 193 | "int main(void){return 0;}\n" 194 | ) 195 | execute_process( 196 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 197 | ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in 198 | ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp 199 | ) 200 | add_executable(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp) 201 | if(ARGN) 202 | add_dependencies(${name} ${ARGN}) 203 | endif(ARGN) 204 | 205 | if(CMAKE_CROSSCOMPILING) 206 | set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross 207 | else() 208 | set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) 209 | endif() 210 | endfunction(GR_GEN_TARGET_DEPS) 211 | -------------------------------------------------------------------------------- /cmake/Modules/GrPlatform.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | if(DEFINED __INCLUDED_GR_PLATFORM_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_PLATFORM_CMAKE TRUE) 24 | 25 | ######################################################################## 26 | # Setup additional defines for OS types 27 | ######################################################################## 28 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 29 | set(LINUX TRUE) 30 | endif() 31 | 32 | if(LINUX AND EXISTS "/etc/debian_version") 33 | set(DEBIAN TRUE) 34 | endif() 35 | 36 | if(LINUX AND EXISTS "/etc/redhat-release") 37 | set(REDHAT TRUE) 38 | endif() 39 | 40 | ######################################################################## 41 | # when the library suffix should be 64 (applies to redhat linux family) 42 | ######################################################################## 43 | if(NOT DEFINED LIB_SUFFIX AND REDHAT AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") 44 | set(LIB_SUFFIX 64) 45 | endif() 46 | set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix") 47 | -------------------------------------------------------------------------------- /cmake/Modules/GrPython.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2010-2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | if(DEFINED __INCLUDED_GR_PYTHON_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_PYTHON_CMAKE TRUE) 24 | 25 | ######################################################################## 26 | # Setup the python interpreter: 27 | # This allows the user to specify a specific interpreter, 28 | # or finds the interpreter via the built-in cmake module. 29 | ######################################################################## 30 | #this allows the user to override PYTHON_EXECUTABLE 31 | if(PYTHON_EXECUTABLE) 32 | 33 | set(PYTHONINTERP_FOUND TRUE) 34 | 35 | #otherwise if not set, try to automatically find it 36 | else(PYTHON_EXECUTABLE) 37 | 38 | #use the built-in find script 39 | find_package(PythonInterp) 40 | 41 | #and if that fails use the find program routine 42 | if(NOT PYTHONINTERP_FOUND) 43 | find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5) 44 | if(PYTHON_EXECUTABLE) 45 | set(PYTHONINTERP_FOUND TRUE) 46 | endif(PYTHON_EXECUTABLE) 47 | endif(NOT PYTHONINTERP_FOUND) 48 | 49 | endif(PYTHON_EXECUTABLE) 50 | 51 | #make the path to the executable appear in the cmake gui 52 | set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") 53 | 54 | #make sure we can use -B with python (introduced in 2.6) 55 | if(PYTHON_EXECUTABLE) 56 | execute_process( 57 | COMMAND ${PYTHON_EXECUTABLE} -B -c "" 58 | OUTPUT_QUIET ERROR_QUIET 59 | RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT 60 | ) 61 | if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) 62 | set(PYTHON_DASH_B "-B") 63 | endif() 64 | endif(PYTHON_EXECUTABLE) 65 | 66 | ######################################################################## 67 | # Check for the existence of a python module: 68 | # - desc a string description of the check 69 | # - mod the name of the module to import 70 | # - cmd an additional command to run 71 | # - have the result variable to set 72 | ######################################################################## 73 | macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) 74 | message(STATUS "") 75 | message(STATUS "Python checking for ${desc}") 76 | execute_process( 77 | COMMAND ${PYTHON_EXECUTABLE} -c " 78 | ######################################### 79 | try: import ${mod} 80 | except: exit(-1) 81 | try: assert ${cmd} 82 | except: exit(-1) 83 | #########################################" 84 | RESULT_VARIABLE ${have} 85 | ) 86 | if(${have} EQUAL 0) 87 | message(STATUS "Python checking for ${desc} - found") 88 | set(${have} TRUE) 89 | else(${have} EQUAL 0) 90 | message(STATUS "Python checking for ${desc} - not found") 91 | set(${have} FALSE) 92 | endif(${have} EQUAL 0) 93 | endmacro(GR_PYTHON_CHECK_MODULE) 94 | 95 | ######################################################################## 96 | # Sets the python installation directory GR_PYTHON_DIR 97 | ######################################################################## 98 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " 99 | from distutils import sysconfig 100 | print sysconfig.get_python_lib(plat_specific=True, prefix='') 101 | " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE 102 | ) 103 | file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) 104 | 105 | ######################################################################## 106 | # Create an always-built target with a unique name 107 | # Usage: GR_UNIQUE_TARGET( ) 108 | ######################################################################## 109 | function(GR_UNIQUE_TARGET desc) 110 | file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) 111 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib 112 | unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] 113 | print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" 114 | OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) 115 | add_custom_target(${_target} ALL DEPENDS ${ARGN}) 116 | endfunction(GR_UNIQUE_TARGET) 117 | 118 | ######################################################################## 119 | # Install python sources (also builds and installs byte-compiled python) 120 | ######################################################################## 121 | function(GR_PYTHON_INSTALL) 122 | include(CMakeParseArgumentsCopy) 123 | CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) 124 | 125 | #################################################################### 126 | if(GR_PYTHON_INSTALL_FILES) 127 | #################################################################### 128 | install(${ARGN}) #installs regular python files 129 | 130 | #create a list of all generated files 131 | unset(pysrcfiles) 132 | unset(pycfiles) 133 | unset(pyofiles) 134 | foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) 135 | get_filename_component(pyfile ${pyfile} ABSOLUTE) 136 | list(APPEND pysrcfiles ${pyfile}) 137 | 138 | #determine if this file is in the source or binary directory 139 | file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) 140 | string(LENGTH "${source_rel_path}" source_rel_path_len) 141 | file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) 142 | string(LENGTH "${binary_rel_path}" binary_rel_path_len) 143 | 144 | #and set the generated path appropriately 145 | if(${source_rel_path_len} GREATER ${binary_rel_path_len}) 146 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) 147 | else() 148 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) 149 | endif() 150 | list(APPEND pycfiles ${pygenfile}c) 151 | list(APPEND pyofiles ${pygenfile}o) 152 | 153 | #ensure generation path exists 154 | get_filename_component(pygen_path ${pygenfile} PATH) 155 | file(MAKE_DIRECTORY ${pygen_path}) 156 | 157 | endforeach(pyfile) 158 | 159 | #the command to generate the pyc files 160 | add_custom_command( 161 | DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} 162 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} 163 | ) 164 | 165 | #the command to generate the pyo files 166 | add_custom_command( 167 | DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} 168 | COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} 169 | ) 170 | 171 | #create install rule and add generated files to target list 172 | set(python_install_gen_targets ${pycfiles} ${pyofiles}) 173 | install(FILES ${python_install_gen_targets} 174 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} 175 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} 176 | ) 177 | 178 | 179 | #################################################################### 180 | elseif(GR_PYTHON_INSTALL_PROGRAMS) 181 | #################################################################### 182 | file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) 183 | 184 | foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) 185 | get_filename_component(pyfile_name ${pyfile} NAME) 186 | get_filename_component(pyfile ${pyfile} ABSOLUTE) 187 | string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") 188 | list(APPEND python_install_gen_targets ${pyexefile}) 189 | 190 | get_filename_component(pyexefile_path ${pyexefile} PATH) 191 | file(MAKE_DIRECTORY ${pyexefile_path}) 192 | 193 | add_custom_command( 194 | OUTPUT ${pyexefile} DEPENDS ${pyfile} 195 | COMMAND ${PYTHON_EXECUTABLE} -c 196 | \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" 197 | COMMENT "Shebangin ${pyfile_name}" 198 | ) 199 | 200 | #on windows, python files need an extension to execute 201 | get_filename_component(pyfile_ext ${pyfile} EXT) 202 | if(WIN32 AND NOT pyfile_ext) 203 | set(pyfile_name "${pyfile_name}.py") 204 | endif() 205 | 206 | install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} 207 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} 208 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} 209 | ) 210 | endforeach(pyfile) 211 | 212 | endif() 213 | 214 | GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) 215 | 216 | endfunction(GR_PYTHON_INSTALL) 217 | 218 | ######################################################################## 219 | # Write the python helper script that generates byte code files 220 | ######################################################################## 221 | file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " 222 | import sys, py_compile 223 | files = sys.argv[1:] 224 | srcs, gens = files[:len(files)/2], files[len(files)/2:] 225 | for src, gen in zip(srcs, gens): 226 | py_compile.compile(file=src, cfile=gen, doraise=True) 227 | ") 228 | -------------------------------------------------------------------------------- /cmake/Modules/GrSwig.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2010-2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | if(DEFINED __INCLUDED_GR_SWIG_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_SWIG_CMAKE TRUE) 24 | 25 | include(GrPython) 26 | 27 | ######################################################################## 28 | # Builds a swig documentation file to be generated into python docstrings 29 | # Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....) 30 | # 31 | # Set the following variable to specify extra dependent targets: 32 | # - GR_SWIG_DOCS_SOURCE_DEPS 33 | # - GR_SWIG_DOCS_TARGET_DEPS 34 | ######################################################################## 35 | function(GR_SWIG_MAKE_DOCS output_file) 36 | find_package(Doxygen) 37 | if(DOXYGEN_FOUND) 38 | 39 | #setup the input files variable list, quote formated 40 | set(input_files) 41 | unset(INPUT_PATHS) 42 | foreach(input_path ${ARGN}) 43 | if (IS_DIRECTORY ${input_path}) #when input path is a directory 44 | file(GLOB input_path_h_files ${input_path}/*.h) 45 | else() #otherwise its just a file, no glob 46 | set(input_path_h_files ${input_path}) 47 | endif() 48 | list(APPEND input_files ${input_path_h_files}) 49 | set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"") 50 | endforeach(input_path) 51 | 52 | #determine the output directory 53 | get_filename_component(name ${output_file} NAME_WE) 54 | get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH) 55 | set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs) 56 | make_directory(${OUTPUT_DIRECTORY}) 57 | 58 | #generate the Doxyfile used by doxygen 59 | configure_file( 60 | ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in 61 | ${OUTPUT_DIRECTORY}/Doxyfile 62 | @ONLY) 63 | 64 | #Create a dummy custom command that depends on other targets 65 | include(GrMiscUtils) 66 | GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS}) 67 | 68 | #call doxygen on the Doxyfile + input headers 69 | add_custom_command( 70 | OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml 71 | DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps} 72 | COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile 73 | COMMENT "Generating doxygen xml for ${name} docs" 74 | ) 75 | 76 | #call the swig_doc script on the xml files 77 | add_custom_command( 78 | OUTPUT ${output_file} 79 | DEPENDS ${input_files} ${OUTPUT_DIRECTORY}/xml/index.xml 80 | COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} 81 | ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py 82 | ${OUTPUT_DIRECTORY}/xml 83 | ${output_file} 84 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen 85 | ) 86 | 87 | else(DOXYGEN_FOUND) 88 | file(WRITE ${output_file} "\n") #no doxygen -> empty file 89 | endif(DOXYGEN_FOUND) 90 | endfunction(GR_SWIG_MAKE_DOCS) 91 | 92 | ######################################################################## 93 | # Build a swig target for the common gnuradio use case. Usage: 94 | # GR_SWIG_MAKE(target ifile ifile ifile...) 95 | # 96 | # Set the following variables before calling: 97 | # - GR_SWIG_FLAGS 98 | # - GR_SWIG_INCLUDE_DIRS 99 | # - GR_SWIG_LIBRARIES 100 | # - GR_SWIG_SOURCE_DEPS 101 | # - GR_SWIG_TARGET_DEPS 102 | # - GR_SWIG_DOC_FILE 103 | # - GR_SWIG_DOC_DIRS 104 | ######################################################################## 105 | macro(GR_SWIG_MAKE name) 106 | set(ifiles ${ARGN}) 107 | 108 | #do swig doc generation if specified 109 | if (GR_SWIG_DOC_FILE) 110 | set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) 111 | set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS}) 112 | GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) 113 | list(APPEND GR_SWIG_SOURCE_DEPS ${GR_SWIG_DOC_FILE}) 114 | endif() 115 | 116 | #append additional include directories 117 | find_package(PythonLibs) 118 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) 119 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) 120 | list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) 121 | list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) 122 | 123 | #determine include dependencies for swig file 124 | execute_process( 125 | COMMAND ${PYTHON_EXECUTABLE} 126 | ${CMAKE_BINARY_DIR}/get_swig_deps.py 127 | "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" 128 | OUTPUT_STRIP_TRAILING_WHITESPACE 129 | OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS 130 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 131 | ) 132 | 133 | #Create a dummy custom command that depends on other targets 134 | include(GrMiscUtils) 135 | GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS}) 136 | set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag) 137 | add_custom_command( 138 | OUTPUT ${tag_file} 139 | DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps} 140 | COMMAND ${CMAKE_COMMAND} -E touch ${tag_file} 141 | ) 142 | 143 | #append the specified include directories 144 | include_directories(${GR_SWIG_INCLUDE_DIRS}) 145 | list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) 146 | 147 | #setup the swig flags with flags and include directories 148 | set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS}) 149 | foreach(dir ${GR_SWIG_INCLUDE_DIRS}) 150 | list(APPEND CMAKE_SWIG_FLAGS "-I${dir}") 151 | endforeach(dir) 152 | 153 | #set the C++ property on the swig .i file so it builds 154 | set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON) 155 | 156 | #setup the actual swig library target to be built 157 | include(UseSWIG) 158 | SWIG_ADD_MODULE(${name} python ${ifiles}) 159 | SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES}) 160 | 161 | endmacro(GR_SWIG_MAKE) 162 | 163 | ######################################################################## 164 | # Install swig targets generated by GR_SWIG_MAKE. Usage: 165 | # GR_SWIG_INSTALL( 166 | # TARGETS target target target... 167 | # [DESTINATION destination] 168 | # [COMPONENT component] 169 | # ) 170 | ######################################################################## 171 | macro(GR_SWIG_INSTALL) 172 | 173 | include(CMakeParseArgumentsCopy) 174 | CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN}) 175 | 176 | foreach(name ${GR_SWIG_INSTALL_TARGETS}) 177 | install(TARGETS ${SWIG_MODULE_${name}_REAL_NAME} 178 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 179 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT} 180 | ) 181 | 182 | include(GrPython) 183 | GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py 184 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 185 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT} 186 | ) 187 | 188 | GR_LIBTOOL( 189 | TARGET ${SWIG_MODULE_${name}_REAL_NAME} 190 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 191 | ) 192 | 193 | endforeach(name) 194 | 195 | endmacro(GR_SWIG_INSTALL) 196 | 197 | ######################################################################## 198 | # Generate a python file that can determine swig dependencies. 199 | # Used by the make macro above to determine extra dependencies. 200 | # When you build C++, CMake figures out the header dependencies. 201 | # This code essentially performs that logic for swig includes. 202 | ######################################################################## 203 | file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py " 204 | 205 | import os, sys, re 206 | 207 | include_matcher = re.compile('[#|%]include\\s*[<|\"](.*)[>|\"]') 208 | include_dirs = sys.argv[2].split(';') 209 | 210 | def get_swig_incs(file_path): 211 | file_contents = open(file_path, 'r').read() 212 | return include_matcher.findall(file_contents, re.MULTILINE) 213 | 214 | def get_swig_deps(file_path, level): 215 | deps = [file_path] 216 | if level == 0: return deps 217 | for inc_file in get_swig_incs(file_path): 218 | for inc_dir in include_dirs: 219 | inc_path = os.path.join(inc_dir, inc_file) 220 | if not os.path.exists(inc_path): continue 221 | deps.extend(get_swig_deps(inc_path, level-1)) 222 | return deps 223 | 224 | if __name__ == '__main__': 225 | ifiles = sys.argv[1].split(';') 226 | deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], []) 227 | #sys.stderr.write(';'.join(set(deps)) + '\\n\\n') 228 | print(';'.join(set(deps))) 229 | ") 230 | -------------------------------------------------------------------------------- /cmake/Modules/GrTest.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2010-2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | if(DEFINED __INCLUDED_GR_TEST_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_TEST_CMAKE TRUE) 24 | 25 | ######################################################################## 26 | # Add a unit test and setup the environment for a unit test. 27 | # Takes the same arguments as the ADD_TEST function. 28 | # 29 | # Before calling set the following variables: 30 | # GR_TEST_TARGET_DEPS - built targets for the library path 31 | # GR_TEST_LIBRARY_DIRS - directories for the library path 32 | # GR_TEST_PYTHON_DIRS - directories for the python path 33 | ######################################################################## 34 | function(GR_ADD_TEST test_name) 35 | 36 | if(WIN32) 37 | #Ensure that the build exe also appears in the PATH. 38 | list(APPEND GR_TEST_TARGET_DEPS ${ARGN}) 39 | 40 | #In the land of windows, all libraries must be in the PATH. 41 | #Since the dependent libraries are not yet installed, 42 | #we must manually set them in the PATH to run tests. 43 | #The following appends the path of a target dependency. 44 | foreach(target ${GR_TEST_TARGET_DEPS}) 45 | get_target_property(location ${target} LOCATION) 46 | if(location) 47 | get_filename_component(path ${location} PATH) 48 | string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path}) 49 | list(APPEND GR_TEST_LIBRARY_DIRS ${path}) 50 | endif(location) 51 | endforeach(target) 52 | 53 | #SWIG generates the python library files into a subdirectory. 54 | #Therefore, we must append this subdirectory into PYTHONPATH. 55 | #Only do this for the python directories matching the following: 56 | foreach(pydir ${GR_TEST_PYTHON_DIRS}) 57 | get_filename_component(name ${pydir} NAME) 58 | if(name MATCHES "^(swig|lib|src)$") 59 | list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE}) 60 | endif() 61 | endforeach(pydir) 62 | endif(WIN32) 63 | 64 | file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir) 65 | file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list? 66 | file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list? 67 | 68 | set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}") 69 | 70 | #http://www.cmake.org/pipermail/cmake/2009-May/029464.html 71 | #Replaced this add test + set environs code with the shell script generation. 72 | #Its nicer to be able to manually run the shell script to diagnose problems. 73 | #ADD_TEST(${ARGV}) 74 | #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}") 75 | 76 | if(UNIX) 77 | set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH") 78 | #set both LD and DYLD paths to cover multiple UNIX OS library paths 79 | list(APPEND libpath "$LD_LIBRARY_PATH" "$DYLD_LIBRARY_PATH") 80 | list(APPEND pypath "$PYTHONPATH") 81 | 82 | #replace list separator with the path separator 83 | string(REPLACE ";" ":" libpath "${libpath}") 84 | string(REPLACE ";" ":" pypath "${pypath}") 85 | list(APPEND environs "PATH=${binpath}" "LD_LIBRARY_PATH=${libpath}" "DYLD_LIBRARY_PATH=${libpath}" "PYTHONPATH=${pypath}") 86 | 87 | #generate a bat file that sets the environment and runs the test 88 | find_program(SHELL sh) 89 | set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh) 90 | file(WRITE ${sh_file} "#!${SHELL}\n") 91 | #each line sets an environment variable 92 | foreach(environ ${environs}) 93 | file(APPEND ${sh_file} "export ${environ}\n") 94 | endforeach(environ) 95 | #load the command to run with its arguments 96 | foreach(arg ${ARGN}) 97 | file(APPEND ${sh_file} "${arg} ") 98 | endforeach(arg) 99 | file(APPEND ${sh_file} "\n") 100 | 101 | #make the shell file executable 102 | execute_process(COMMAND chmod +x ${sh_file}) 103 | 104 | add_test(${test_name} ${SHELL} ${sh_file}) 105 | 106 | endif(UNIX) 107 | 108 | if(WIN32) 109 | list(APPEND libpath ${DLL_PATHS} "%PATH%") 110 | list(APPEND pypath "%PYTHONPATH%") 111 | 112 | #replace list separator with the path separator (escaped) 113 | string(REPLACE ";" "\\;" libpath "${libpath}") 114 | string(REPLACE ";" "\\;" pypath "${pypath}") 115 | list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}") 116 | 117 | #generate a bat file that sets the environment and runs the test 118 | set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat) 119 | file(WRITE ${bat_file} "@echo off\n") 120 | #each line sets an environment variable 121 | foreach(environ ${environs}) 122 | file(APPEND ${bat_file} "SET ${environ}\n") 123 | endforeach(environ) 124 | #load the command to run with its arguments 125 | foreach(arg ${ARGN}) 126 | file(APPEND ${bat_file} "${arg} ") 127 | endforeach(arg) 128 | file(APPEND ${bat_file} "\n") 129 | 130 | add_test(${test_name} ${bat_file}) 131 | endif(WIN32) 132 | 133 | endfunction(GR_ADD_TEST) 134 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Setup dependencies 22 | ######################################################################## 23 | find_package(Doxygen) 24 | 25 | ######################################################################## 26 | # Begin conditional configuration 27 | ######################################################################## 28 | if(ENABLE_DOXYGEN) 29 | 30 | ######################################################################## 31 | # Add subdirectories 32 | ######################################################################## 33 | add_subdirectory(doxygen) 34 | 35 | endif(ENABLE_DOXYGEN) 36 | -------------------------------------------------------------------------------- /docs/doxygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Create the doxygen configuration file 22 | ######################################################################## 23 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} top_srcdir) 24 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} top_builddir) 25 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} abs_top_srcdir) 26 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} abs_top_builddir) 27 | 28 | set(HAVE_DOT ${DOXYGEN_DOT_FOUND}) 29 | set(enable_html_docs YES) 30 | set(enable_latex_docs NO) 31 | set(enable_xml_docs YES) 32 | 33 | configure_file( 34 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 35 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 36 | @ONLY) 37 | 38 | set(BUILT_DIRS ${CMAKE_CURRENT_BINARY_DIR}/xml ${CMAKE_CURRENT_BINARY_DIR}/html) 39 | 40 | ######################################################################## 41 | # Make and install doxygen docs 42 | ######################################################################## 43 | add_custom_command( 44 | OUTPUT ${BUILT_DIRS} 45 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 46 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 47 | COMMENT "Generating documentation with doxygen" 48 | ) 49 | 50 | add_custom_target(doxygen_target ALL DEPENDS ${BUILT_DIRS}) 51 | 52 | install(DIRECTORY ${BUILT_DIRS} DESTINATION ${GR_PKG_DOC_DIR}) 53 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/.gitignore: -------------------------------------------------------------------------------- 1 | /Makefile 2 | /Makefile.in 3 | 4 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2007,2009,2011 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | 22 | include $(top_srcdir)/Makefile.common 23 | 24 | EXTRA_DIST = \ 25 | example/aadvark.cc \ 26 | example/aadvark.h \ 27 | example/Doxyfile \ 28 | example/xml/aadvark_8cc.xml \ 29 | example/xml/aadvark_8h.xml \ 30 | example/xml/classAadvark.xml \ 31 | example/xml/combine.xslt \ 32 | example/xml/compound.xsd \ 33 | example/xml/index.xml \ 34 | example/xml/index.xsd 35 | 36 | if PYTHON 37 | utilspythondir = $(grpythondir)/doxyxml 38 | 39 | TESTS = \ 40 | run_tests 41 | 42 | nobase_utilspython_PYTHON = \ 43 | __init__.py \ 44 | base.py \ 45 | doxyindex.py \ 46 | text.py \ 47 | generated/__init__.py \ 48 | generated/index.py \ 49 | generated/indexsuper.py \ 50 | generated/compound.py \ 51 | generated/compoundsuper.py 52 | endif -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | """ 22 | Python interface to contents of doxygen xml documentation. 23 | 24 | Example use: 25 | See the contents of the example folder for the C++ and 26 | doxygen-generated xml used in this example. 27 | 28 | >>> # Parse the doxygen docs. 29 | >>> import os 30 | >>> this_dir = os.path.dirname(globals()['__file__']) 31 | >>> xml_path = this_dir + "/example/xml/" 32 | >>> di = DoxyIndex(xml_path) 33 | 34 | Get a list of all top-level objects. 35 | 36 | >>> print([mem.name() for mem in di.members()]) 37 | [u'Aadvark', u'aadvarky_enough', u'main'] 38 | 39 | Get all functions. 40 | 41 | >>> print([mem.name() for mem in di.in_category(DoxyFunction)]) 42 | [u'aadvarky_enough', u'main'] 43 | 44 | Check if an object is present. 45 | 46 | >>> di.has_member(u'Aadvark') 47 | True 48 | >>> di.has_member(u'Fish') 49 | False 50 | 51 | Get an item by name and check its properties. 52 | 53 | >>> aad = di.get_member(u'Aadvark') 54 | >>> print(aad.brief_description) 55 | Models the mammal Aadvark. 56 | >>> print(aad.detailed_description) 57 | Sadly the model is incomplete and cannot capture all aspects of an aadvark yet. 58 | 59 | This line is uninformative and is only to test line breaks in the comments. 60 | >>> [mem.name() for mem in aad.members()] 61 | [u'aadvarkness', u'print', u'Aadvark', u'get_aadvarkness'] 62 | >>> aad.get_member(u'print').brief_description 63 | u'Outputs the vital aadvark statistics.' 64 | 65 | """ 66 | 67 | from doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther 68 | 69 | def _test(): 70 | import os 71 | this_dir = os.path.dirname(globals()['__file__']) 72 | xml_path = this_dir + "/example/xml/" 73 | di = DoxyIndex(xml_path) 74 | # Get the Aadvark class 75 | aad = di.get_member('Aadvark') 76 | aad.brief_description 77 | import doctest 78 | return doctest.testmod() 79 | 80 | if __name__ == "__main__": 81 | _test() 82 | 83 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/base.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | """ 22 | A base class is created. 23 | 24 | Classes based upon this are used to make more user-friendly interfaces 25 | to the doxygen xml docs than the generated classes provide. 26 | """ 27 | 28 | import os 29 | import pdb 30 | 31 | from xml.parsers.expat import ExpatError 32 | 33 | from generated import compound 34 | 35 | 36 | class Base(object): 37 | 38 | class Duplicate(StandardError): 39 | pass 40 | 41 | class NoSuchMember(StandardError): 42 | pass 43 | 44 | class ParsingError(StandardError): 45 | pass 46 | 47 | def __init__(self, parse_data, top=None): 48 | self._parsed = False 49 | self._error = False 50 | self._parse_data = parse_data 51 | self._members = [] 52 | self._dict_members = {} 53 | self._in_category = {} 54 | self._data = {} 55 | if top is not None: 56 | self._xml_path = top._xml_path 57 | # Set up holder of references 58 | else: 59 | top = self 60 | self._refs = {} 61 | self._xml_path = parse_data 62 | self.top = top 63 | 64 | @classmethod 65 | def from_refid(cls, refid, top=None): 66 | """ Instantiate class from a refid rather than parsing object. """ 67 | # First check to see if its already been instantiated. 68 | if top is not None and refid in top._refs: 69 | return top._refs[refid] 70 | # Otherwise create a new instance and set refid. 71 | inst = cls(None, top=top) 72 | inst.refid = refid 73 | inst.add_ref(inst) 74 | return inst 75 | 76 | @classmethod 77 | def from_parse_data(cls, parse_data, top=None): 78 | refid = getattr(parse_data, 'refid', None) 79 | if refid is not None and top is not None and refid in top._refs: 80 | return top._refs[refid] 81 | inst = cls(parse_data, top=top) 82 | if refid is not None: 83 | inst.refid = refid 84 | inst.add_ref(inst) 85 | return inst 86 | 87 | def add_ref(self, obj): 88 | if hasattr(obj, 'refid'): 89 | self.top._refs[obj.refid] = obj 90 | 91 | mem_classes = [] 92 | 93 | def get_cls(self, mem): 94 | for cls in self.mem_classes: 95 | if cls.can_parse(mem): 96 | return cls 97 | raise StandardError(("Did not find a class for object '%s'." \ 98 | % (mem.get_name()))) 99 | 100 | def convert_mem(self, mem): 101 | try: 102 | cls = self.get_cls(mem) 103 | converted = cls.from_parse_data(mem, self.top) 104 | if converted is None: 105 | raise StandardError('No class matched this object.') 106 | self.add_ref(converted) 107 | return converted 108 | except StandardError, e: 109 | print e 110 | 111 | @classmethod 112 | def includes(cls, inst): 113 | return isinstance(inst, cls) 114 | 115 | @classmethod 116 | def can_parse(cls, obj): 117 | return False 118 | 119 | def _parse(self): 120 | self._parsed = True 121 | 122 | def _get_dict_members(self, cat=None): 123 | """ 124 | For given category a dictionary is returned mapping member names to 125 | members of that category. For names that are duplicated the name is 126 | mapped to None. 127 | """ 128 | self.confirm_no_error() 129 | if cat not in self._dict_members: 130 | new_dict = {} 131 | for mem in self.in_category(cat): 132 | if mem.name() not in new_dict: 133 | new_dict[mem.name()] = mem 134 | else: 135 | new_dict[mem.name()] = self.Duplicate 136 | self._dict_members[cat] = new_dict 137 | return self._dict_members[cat] 138 | 139 | def in_category(self, cat): 140 | self.confirm_no_error() 141 | if cat is None: 142 | return self._members 143 | if cat not in self._in_category: 144 | self._in_category[cat] = [mem for mem in self._members 145 | if cat.includes(mem)] 146 | return self._in_category[cat] 147 | 148 | def get_member(self, name, cat=None): 149 | self.confirm_no_error() 150 | # Check if it's in a namespace or class. 151 | bits = name.split('::') 152 | first = bits[0] 153 | rest = '::'.join(bits[1:]) 154 | member = self._get_dict_members(cat).get(first, self.NoSuchMember) 155 | # Raise any errors that are returned. 156 | if member in set([self.NoSuchMember, self.Duplicate]): 157 | raise member() 158 | if rest: 159 | return member.get_member(rest, cat=cat) 160 | return member 161 | 162 | def has_member(self, name, cat=None): 163 | try: 164 | mem = self.get_member(name, cat=cat) 165 | return True 166 | except self.NoSuchMember: 167 | return False 168 | 169 | def data(self): 170 | self.confirm_no_error() 171 | return self._data 172 | 173 | def members(self): 174 | self.confirm_no_error() 175 | return self._members 176 | 177 | def process_memberdefs(self): 178 | mdtss = [] 179 | for sec in self._retrieved_data.compounddef.sectiondef: 180 | mdtss += sec.memberdef 181 | # At the moment we lose all information associated with sections. 182 | # Sometimes a memberdef is in several sectiondef. 183 | # We make sure we don't get duplicates here. 184 | uniques = set([]) 185 | for mem in mdtss: 186 | converted = self.convert_mem(mem) 187 | pair = (mem.name, mem.__class__) 188 | if pair not in uniques: 189 | uniques.add(pair) 190 | self._members.append(converted) 191 | 192 | def retrieve_data(self): 193 | filename = os.path.join(self._xml_path, self.refid + '.xml') 194 | try: 195 | self._retrieved_data = compound.parse(filename) 196 | except ExpatError: 197 | print('Error in xml in file %s' % filename) 198 | self._error = True 199 | self._retrieved_data = None 200 | 201 | def check_parsed(self): 202 | if not self._parsed: 203 | self._parse() 204 | 205 | def confirm_no_error(self): 206 | self.check_parsed() 207 | if self._error: 208 | raise self.ParsingError() 209 | 210 | def error(self): 211 | self.check_parsed() 212 | return self._error 213 | 214 | def name(self): 215 | # first see if we can do it without processing. 216 | if self._parse_data is not None: 217 | return self._parse_data.name 218 | self.check_parsed() 219 | return self._retrieved_data.compounddef.name 220 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/doxyindex.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | """ 22 | Classes providing more user-friendly interfaces to the doxygen xml 23 | docs than the generated classes provide. 24 | """ 25 | 26 | import os 27 | 28 | from generated import index 29 | from base import Base 30 | from text import description 31 | 32 | class DoxyIndex(Base): 33 | """ 34 | Parses a doxygen xml directory. 35 | """ 36 | 37 | __module__ = "gnuradio.utils.doxyxml" 38 | 39 | def _parse(self): 40 | if self._parsed: 41 | return 42 | super(DoxyIndex, self)._parse() 43 | self._root = index.parse(os.path.join(self._xml_path, 'index.xml')) 44 | for mem in self._root.compound: 45 | converted = self.convert_mem(mem) 46 | # For files we want the contents to be accessible directly 47 | # from the parent rather than having to go through the file 48 | # object. 49 | if self.get_cls(mem) == DoxyFile: 50 | if mem.name.endswith('.h'): 51 | self._members += converted.members() 52 | self._members.append(converted) 53 | else: 54 | self._members.append(converted) 55 | 56 | 57 | def generate_swig_doc_i(self): 58 | """ 59 | %feature("docstring") gr_make_align_on_samplenumbers_ss::align_state " 60 | Wraps the C++: gr_align_on_samplenumbers_ss::align_state"; 61 | """ 62 | pass 63 | 64 | 65 | class DoxyCompMem(Base): 66 | 67 | 68 | kind = None 69 | 70 | def __init__(self, *args, **kwargs): 71 | super(DoxyCompMem, self).__init__(*args, **kwargs) 72 | 73 | @classmethod 74 | def can_parse(cls, obj): 75 | return obj.kind == cls.kind 76 | 77 | def set_descriptions(self, parse_data): 78 | bd = description(getattr(parse_data, 'briefdescription', None)) 79 | dd = description(getattr(parse_data, 'detaileddescription', None)) 80 | self._data['brief_description'] = bd 81 | self._data['detailed_description'] = dd 82 | 83 | class DoxyCompound(DoxyCompMem): 84 | pass 85 | 86 | class DoxyMember(DoxyCompMem): 87 | pass 88 | 89 | 90 | class DoxyFunction(DoxyMember): 91 | 92 | __module__ = "gnuradio.utils.doxyxml" 93 | 94 | kind = 'function' 95 | 96 | def _parse(self): 97 | if self._parsed: 98 | return 99 | super(DoxyFunction, self)._parse() 100 | self.set_descriptions(self._parse_data) 101 | self._data['params'] = [] 102 | prms = self._parse_data.param 103 | for prm in prms: 104 | self._data['params'].append(DoxyParam(prm)) 105 | 106 | brief_description = property(lambda self: self.data()['brief_description']) 107 | detailed_description = property(lambda self: self.data()['detailed_description']) 108 | params = property(lambda self: self.data()['params']) 109 | 110 | Base.mem_classes.append(DoxyFunction) 111 | 112 | 113 | class DoxyParam(DoxyMember): 114 | 115 | __module__ = "gnuradio.utils.doxyxml" 116 | 117 | def _parse(self): 118 | if self._parsed: 119 | return 120 | super(DoxyParam, self)._parse() 121 | self.set_descriptions(self._parse_data) 122 | self._data['declname'] = self._parse_data.declname 123 | 124 | brief_description = property(lambda self: self.data()['brief_description']) 125 | detailed_description = property(lambda self: self.data()['detailed_description']) 126 | declname = property(lambda self: self.data()['declname']) 127 | 128 | class DoxyClass(DoxyCompound): 129 | 130 | __module__ = "gnuradio.utils.doxyxml" 131 | 132 | kind = 'class' 133 | 134 | def _parse(self): 135 | if self._parsed: 136 | return 137 | super(DoxyClass, self)._parse() 138 | self.retrieve_data() 139 | if self._error: 140 | return 141 | self.set_descriptions(self._retrieved_data.compounddef) 142 | # Sectiondef.kind tells about whether private or public. 143 | # We just ignore this for now. 144 | self.process_memberdefs() 145 | 146 | brief_description = property(lambda self: self.data()['brief_description']) 147 | detailed_description = property(lambda self: self.data()['detailed_description']) 148 | 149 | Base.mem_classes.append(DoxyClass) 150 | 151 | 152 | class DoxyFile(DoxyCompound): 153 | 154 | __module__ = "gnuradio.utils.doxyxml" 155 | 156 | kind = 'file' 157 | 158 | def _parse(self): 159 | if self._parsed: 160 | return 161 | super(DoxyFile, self)._parse() 162 | self.retrieve_data() 163 | self.set_descriptions(self._retrieved_data.compounddef) 164 | if self._error: 165 | return 166 | self.process_memberdefs() 167 | 168 | brief_description = property(lambda self: self.data()['brief_description']) 169 | detailed_description = property(lambda self: self.data()['detailed_description']) 170 | 171 | Base.mem_classes.append(DoxyFile) 172 | 173 | 174 | class DoxyNamespace(DoxyCompound): 175 | 176 | __module__ = "gnuradio.utils.doxyxml" 177 | 178 | kind = 'namespace' 179 | 180 | Base.mem_classes.append(DoxyNamespace) 181 | 182 | 183 | class DoxyGroup(DoxyCompound): 184 | 185 | __module__ = "gnuradio.utils.doxyxml" 186 | 187 | kind = 'group' 188 | 189 | def _parse(self): 190 | if self._parsed: 191 | return 192 | super(DoxyGroup, self)._parse() 193 | self.retrieve_data() 194 | if self._error: 195 | return 196 | cdef = self._retrieved_data.compounddef 197 | self._data['title'] = description(cdef.title) 198 | # Process inner groups 199 | grps = cdef.innergroup 200 | for grp in grps: 201 | converted = DoxyGroup.from_refid(grp.refid, top=self.top) 202 | self._members.append(converted) 203 | # Process inner classes 204 | klasses = cdef.innerclass 205 | for kls in klasses: 206 | converted = DoxyClass.from_refid(kls.refid, top=self.top) 207 | self._members.append(converted) 208 | # Process normal members 209 | self.process_memberdefs() 210 | 211 | title = property(lambda self: self.data()['title']) 212 | 213 | 214 | Base.mem_classes.append(DoxyGroup) 215 | 216 | 217 | class DoxyFriend(DoxyMember): 218 | 219 | __module__ = "gnuradio.utils.doxyxml" 220 | 221 | kind = 'friend' 222 | 223 | Base.mem_classes.append(DoxyFriend) 224 | 225 | 226 | class DoxyOther(Base): 227 | 228 | __module__ = "gnuradio.utils.doxyxml" 229 | 230 | kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 'dir', 'page']) 231 | 232 | @classmethod 233 | def can_parse(cls, obj): 234 | return obj.kind in cls.kinds 235 | 236 | Base.mem_classes.append(DoxyOther) 237 | 238 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/aadvark.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2010 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GNU Radio 6 | * 7 | * GNU Radio is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * GNU Radio is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GNU Radio; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | #include 23 | #include "aadvark.h" 24 | 25 | void Aadvark::print() { 26 | std::cout << "aadvark is " << aadvarkness << "/10 aadvarky" << std::endl; 27 | } 28 | 29 | Aadvark::Aadvark(int aaness): aadvarkness(aaness) {} 30 | 31 | bool aadvarky_enough(Aadvark aad) { 32 | if (aad.get_aadvarkness() > 6) 33 | return true; 34 | else 35 | return false; 36 | } 37 | 38 | int Aadvark::get_aadvarkness() { 39 | return aadvarkness; 40 | } 41 | 42 | int main() { 43 | Aadvark arold = Aadvark(6); 44 | arold.print(); 45 | if (aadvarky_enough(arold)) 46 | std::cout << "He is aadvarky enough" << std::endl; 47 | else 48 | std::cout << "He is not aadvarky enough" << std::endl; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/aadvark.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2010 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GNU Radio 6 | * 7 | * GNU Radio is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * GNU Radio is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GNU Radio; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | #include 23 | 24 | /*! 25 | * \brief Models the mammal Aadvark. 26 | * 27 | * Sadly the model is incomplete and cannot capture all aspects of an aadvark yet. 28 | * 29 | * This line is uninformative and is only to test line breaks in the comments. 30 | */ 31 | class Aadvark { 32 | public: 33 | //! \brief Outputs the vital aadvark statistics. 34 | void print(); 35 | //! \param aaness The aadvarkness of an aadvark is a measure of how aadvarky it is. 36 | Aadvark(int aaness); 37 | int get_aadvarkness(); 38 | private: 39 | int aadvarkness; 40 | }; 41 | 42 | bool aadvarky_enough(Aadvark aad); 43 | 44 | int main(); 45 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/aadvark_8cc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | aadvark.cc 5 | iostream 6 | aadvark.h 7 | aadvark.cc 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | bool 22 | bool aadvarky_enough 23 | (Aadvark aad) 24 | aadvarky_enough 25 | 26 | Aadvark 27 | aad 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | int 39 | int main 40 | () 41 | main 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | #include<iostream> 57 | #include"aadvark.h" 58 | 59 | voidAadvark::print(){ 60 | std::cout<<"aadvarkis"<<aadvarkness<<"/10aadvarky"<<std::endl; 61 | } 62 | 63 | Aadvark::Aadvark(intaaness):aadvarkness(aaness){} 64 | 65 | boolaadvarky_enough(Aadvarkaad){ 66 | if(aad.get_aadvarkness()>6) 67 | returntrue; 68 | else 69 | returnfalse; 70 | } 71 | 72 | intAadvark::get_aadvarkness(){ 73 | returnaadvarkness; 74 | } 75 | 76 | intmain(){ 77 | Aadvarkarold=Aadvark(6); 78 | arold.print(); 79 | if(aadvarky_enough(arold)) 80 | std::cout<<"Heisaadvarkyenough"<<std::endl; 81 | else 82 | std::cout<<"Heisnotaadvarkyenough"<<std::endl; 83 | } 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/aadvark_8h.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | aadvark.h 5 | iostream 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Aadvark 18 | 19 | 20 | bool 21 | bool aadvarky_enough 22 | (Aadvark aad) 23 | aadvarky_enough 24 | 25 | Aadvark 26 | aad 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | int 38 | int main 39 | () 40 | main 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | #include<iostream> 56 | 57 | classAadvark{ 58 | public: 59 | voidprint(); 60 | Aadvark(intaaness); 61 | intget_aadvarkness(); 62 | private: 63 | intaadvarkness; 64 | }; 65 | 66 | boolaadvarky_enough(Aadvarkaad); 67 | 68 | intmain(); 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/classAadvark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aadvark 5 | aadvark.h 6 | 7 | 8 | int 9 | int Aadvark::aadvarkness 10 | 11 | aadvarkness 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | void 24 | void Aadvark::print 25 | () 26 | print 27 | 28 | Outputs the vital aadvark statistics. 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Aadvark::Aadvark 38 | (int aaness) 39 | Aadvark 40 | 41 | int 42 | aaness 43 | 44 | 45 | 46 | 47 | 48 | 49 | aaness 50 | 51 | 52 | The aadvarkness of an aadvark is a measure of how aadvarky it is. 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | int 62 | int Aadvark::get_aadvarkness 63 | () 64 | get_aadvarkness 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Models the mammal Aadvark. 76 | 77 | Sadly the model is incomplete and cannot capture all aspects of an aadvark yet.This line is uninformative and is only to test line breaks in the comments. 78 | 79 | 80 | AadvarkAadvark 81 | Aadvarkaadvarkness 82 | Aadvarkget_aadvarkness 83 | Aadvarkprint 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/combine.xslt: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Aadvark 4 | aadvarkness 5 | print 6 | Aadvark 7 | get_aadvarkness 8 | 9 | aadvark.cc 10 | aadvarky_enough 11 | main 12 | 13 | aadvark.h 14 | aadvarky_enough 15 | main 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/example/xml/index.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Contains generated files produced by generateDS.py. 3 | 4 | These do the real work of parsing the doxygen xml files but the 5 | resultant classes are not very friendly to navigate so the rest of the 6 | doxyxml module processes them further. 7 | """ 8 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Generated Mon Feb 9 19:08:05 2009 by generateDS.py. 5 | """ 6 | 7 | from xml.dom import minidom 8 | 9 | import os 10 | import sys 11 | import compound 12 | 13 | import indexsuper as supermod 14 | 15 | class DoxygenTypeSub(supermod.DoxygenType): 16 | def __init__(self, version=None, compound=None): 17 | supermod.DoxygenType.__init__(self, version, compound) 18 | 19 | def find_compounds_and_members(self, details): 20 | """ 21 | Returns a list of all compounds and their members which match details 22 | """ 23 | 24 | results = [] 25 | for compound in self.compound: 26 | members = compound.find_members(details) 27 | if members: 28 | results.append([compound, members]) 29 | else: 30 | if details.match(compound): 31 | results.append([compound, []]) 32 | 33 | return results 34 | 35 | supermod.DoxygenType.subclass = DoxygenTypeSub 36 | # end class DoxygenTypeSub 37 | 38 | 39 | class CompoundTypeSub(supermod.CompoundType): 40 | def __init__(self, kind=None, refid=None, name='', member=None): 41 | supermod.CompoundType.__init__(self, kind, refid, name, member) 42 | 43 | def find_members(self, details): 44 | """ 45 | Returns a list of all members which match details 46 | """ 47 | 48 | results = [] 49 | 50 | for member in self.member: 51 | if details.match(member): 52 | results.append(member) 53 | 54 | return results 55 | 56 | supermod.CompoundType.subclass = CompoundTypeSub 57 | # end class CompoundTypeSub 58 | 59 | 60 | class MemberTypeSub(supermod.MemberType): 61 | 62 | def __init__(self, kind=None, refid=None, name=''): 63 | supermod.MemberType.__init__(self, kind, refid, name) 64 | 65 | supermod.MemberType.subclass = MemberTypeSub 66 | # end class MemberTypeSub 67 | 68 | 69 | def parse(inFilename): 70 | 71 | doc = minidom.parse(inFilename) 72 | rootNode = doc.documentElement 73 | rootObj = supermod.DoxygenType.factory() 74 | rootObj.build(rootNode) 75 | 76 | return rootObj 77 | 78 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/indexsuper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # Generated Thu Jun 11 18:43:54 2009 by generateDS.py. 5 | # 6 | 7 | import sys 8 | import getopt 9 | from string import lower as str_lower 10 | from xml.dom import minidom 11 | from xml.dom import Node 12 | 13 | # 14 | # User methods 15 | # 16 | # Calls to the methods in these classes are generated by generateDS.py. 17 | # You can replace these methods by re-implementing the following class 18 | # in a module named generatedssuper.py. 19 | 20 | try: 21 | from generatedssuper import GeneratedsSuper 22 | except ImportError, exp: 23 | 24 | class GeneratedsSuper: 25 | def format_string(self, input_data, input_name=''): 26 | return input_data 27 | def format_integer(self, input_data, input_name=''): 28 | return '%d' % input_data 29 | def format_float(self, input_data, input_name=''): 30 | return '%f' % input_data 31 | def format_double(self, input_data, input_name=''): 32 | return '%e' % input_data 33 | def format_boolean(self, input_data, input_name=''): 34 | return '%s' % input_data 35 | 36 | 37 | # 38 | # If you have installed IPython you can uncomment and use the following. 39 | # IPython is available from http://ipython.scipy.org/. 40 | # 41 | 42 | ## from IPython.Shell import IPShellEmbed 43 | ## args = '' 44 | ## ipshell = IPShellEmbed(args, 45 | ## banner = 'Dropping into IPython', 46 | ## exit_msg = 'Leaving Interpreter, back to program.') 47 | 48 | # Then use the following line where and when you want to drop into the 49 | # IPython shell: 50 | # ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') 51 | 52 | # 53 | # Globals 54 | # 55 | 56 | ExternalEncoding = 'ascii' 57 | 58 | # 59 | # Support/utility functions. 60 | # 61 | 62 | def showIndent(outfile, level): 63 | for idx in range(level): 64 | outfile.write(' ') 65 | 66 | def quote_xml(inStr): 67 | s1 = (isinstance(inStr, basestring) and inStr or 68 | '%s' % inStr) 69 | s1 = s1.replace('&', '&') 70 | s1 = s1.replace('<', '<') 71 | s1 = s1.replace('>', '>') 72 | return s1 73 | 74 | def quote_attrib(inStr): 75 | s1 = (isinstance(inStr, basestring) and inStr or 76 | '%s' % inStr) 77 | s1 = s1.replace('&', '&') 78 | s1 = s1.replace('<', '<') 79 | s1 = s1.replace('>', '>') 80 | if '"' in s1: 81 | if "'" in s1: 82 | s1 = '"%s"' % s1.replace('"', """) 83 | else: 84 | s1 = "'%s'" % s1 85 | else: 86 | s1 = '"%s"' % s1 87 | return s1 88 | 89 | def quote_python(inStr): 90 | s1 = inStr 91 | if s1.find("'") == -1: 92 | if s1.find('\n') == -1: 93 | return "'%s'" % s1 94 | else: 95 | return "'''%s'''" % s1 96 | else: 97 | if s1.find('"') != -1: 98 | s1 = s1.replace('"', '\\"') 99 | if s1.find('\n') == -1: 100 | return '"%s"' % s1 101 | else: 102 | return '"""%s"""' % s1 103 | 104 | 105 | class MixedContainer: 106 | # Constants for category: 107 | CategoryNone = 0 108 | CategoryText = 1 109 | CategorySimple = 2 110 | CategoryComplex = 3 111 | # Constants for content_type: 112 | TypeNone = 0 113 | TypeText = 1 114 | TypeString = 2 115 | TypeInteger = 3 116 | TypeFloat = 4 117 | TypeDecimal = 5 118 | TypeDouble = 6 119 | TypeBoolean = 7 120 | def __init__(self, category, content_type, name, value): 121 | self.category = category 122 | self.content_type = content_type 123 | self.name = name 124 | self.value = value 125 | def getCategory(self): 126 | return self.category 127 | def getContenttype(self, content_type): 128 | return self.content_type 129 | def getValue(self): 130 | return self.value 131 | def getName(self): 132 | return self.name 133 | def export(self, outfile, level, name, namespace): 134 | if self.category == MixedContainer.CategoryText: 135 | outfile.write(self.value) 136 | elif self.category == MixedContainer.CategorySimple: 137 | self.exportSimple(outfile, level, name) 138 | else: # category == MixedContainer.CategoryComplex 139 | self.value.export(outfile, level, namespace,name) 140 | def exportSimple(self, outfile, level, name): 141 | if self.content_type == MixedContainer.TypeString: 142 | outfile.write('<%s>%s' % (self.name, self.value, self.name)) 143 | elif self.content_type == MixedContainer.TypeInteger or \ 144 | self.content_type == MixedContainer.TypeBoolean: 145 | outfile.write('<%s>%d' % (self.name, self.value, self.name)) 146 | elif self.content_type == MixedContainer.TypeFloat or \ 147 | self.content_type == MixedContainer.TypeDecimal: 148 | outfile.write('<%s>%f' % (self.name, self.value, self.name)) 149 | elif self.content_type == MixedContainer.TypeDouble: 150 | outfile.write('<%s>%g' % (self.name, self.value, self.name)) 151 | def exportLiteral(self, outfile, level, name): 152 | if self.category == MixedContainer.CategoryText: 153 | showIndent(outfile, level) 154 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 155 | (self.category, self.content_type, self.name, self.value)) 156 | elif self.category == MixedContainer.CategorySimple: 157 | showIndent(outfile, level) 158 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 159 | (self.category, self.content_type, self.name, self.value)) 160 | else: # category == MixedContainer.CategoryComplex 161 | showIndent(outfile, level) 162 | outfile.write('MixedContainer(%d, %d, "%s",\n' % \ 163 | (self.category, self.content_type, self.name,)) 164 | self.value.exportLiteral(outfile, level + 1) 165 | showIndent(outfile, level) 166 | outfile.write(')\n') 167 | 168 | 169 | class _MemberSpec(object): 170 | def __init__(self, name='', data_type='', container=0): 171 | self.name = name 172 | self.data_type = data_type 173 | self.container = container 174 | def set_name(self, name): self.name = name 175 | def get_name(self): return self.name 176 | def set_data_type(self, data_type): self.data_type = data_type 177 | def get_data_type(self): return self.data_type 178 | def set_container(self, container): self.container = container 179 | def get_container(self): return self.container 180 | 181 | 182 | # 183 | # Data representation classes. 184 | # 185 | 186 | class DoxygenType(GeneratedsSuper): 187 | subclass = None 188 | superclass = None 189 | def __init__(self, version=None, compound=None): 190 | self.version = version 191 | if compound is None: 192 | self.compound = [] 193 | else: 194 | self.compound = compound 195 | def factory(*args_, **kwargs_): 196 | if DoxygenType.subclass: 197 | return DoxygenType.subclass(*args_, **kwargs_) 198 | else: 199 | return DoxygenType(*args_, **kwargs_) 200 | factory = staticmethod(factory) 201 | def get_compound(self): return self.compound 202 | def set_compound(self, compound): self.compound = compound 203 | def add_compound(self, value): self.compound.append(value) 204 | def insert_compound(self, index, value): self.compound[index] = value 205 | def get_version(self): return self.version 206 | def set_version(self, version): self.version = version 207 | def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''): 208 | showIndent(outfile, level) 209 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 210 | self.exportAttributes(outfile, level, namespace_, name_='DoxygenType') 211 | if self.hasContent_(): 212 | outfile.write('>\n') 213 | self.exportChildren(outfile, level + 1, namespace_, name_) 214 | showIndent(outfile, level) 215 | outfile.write('\n' % (namespace_, name_)) 216 | else: 217 | outfile.write(' />\n') 218 | def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'): 219 | outfile.write(' version=%s' % (self.format_string(quote_attrib(self.version).encode(ExternalEncoding), input_name='version'), )) 220 | def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'): 221 | for compound_ in self.compound: 222 | compound_.export(outfile, level, namespace_, name_='compound') 223 | def hasContent_(self): 224 | if ( 225 | self.compound is not None 226 | ): 227 | return True 228 | else: 229 | return False 230 | def exportLiteral(self, outfile, level, name_='DoxygenType'): 231 | level += 1 232 | self.exportLiteralAttributes(outfile, level, name_) 233 | if self.hasContent_(): 234 | self.exportLiteralChildren(outfile, level, name_) 235 | def exportLiteralAttributes(self, outfile, level, name_): 236 | if self.version is not None: 237 | showIndent(outfile, level) 238 | outfile.write('version = %s,\n' % (self.version,)) 239 | def exportLiteralChildren(self, outfile, level, name_): 240 | showIndent(outfile, level) 241 | outfile.write('compound=[\n') 242 | level += 1 243 | for compound in self.compound: 244 | showIndent(outfile, level) 245 | outfile.write('model_.compound(\n') 246 | compound.exportLiteral(outfile, level, name_='compound') 247 | showIndent(outfile, level) 248 | outfile.write('),\n') 249 | level -= 1 250 | showIndent(outfile, level) 251 | outfile.write('],\n') 252 | def build(self, node_): 253 | attrs = node_.attributes 254 | self.buildAttributes(attrs) 255 | for child_ in node_.childNodes: 256 | nodeName_ = child_.nodeName.split(':')[-1] 257 | self.buildChildren(child_, nodeName_) 258 | def buildAttributes(self, attrs): 259 | if attrs.get('version'): 260 | self.version = attrs.get('version').value 261 | def buildChildren(self, child_, nodeName_): 262 | if child_.nodeType == Node.ELEMENT_NODE and \ 263 | nodeName_ == 'compound': 264 | obj_ = CompoundType.factory() 265 | obj_.build(child_) 266 | self.compound.append(obj_) 267 | # end class DoxygenType 268 | 269 | 270 | class CompoundType(GeneratedsSuper): 271 | subclass = None 272 | superclass = None 273 | def __init__(self, kind=None, refid=None, name=None, member=None): 274 | self.kind = kind 275 | self.refid = refid 276 | self.name = name 277 | if member is None: 278 | self.member = [] 279 | else: 280 | self.member = member 281 | def factory(*args_, **kwargs_): 282 | if CompoundType.subclass: 283 | return CompoundType.subclass(*args_, **kwargs_) 284 | else: 285 | return CompoundType(*args_, **kwargs_) 286 | factory = staticmethod(factory) 287 | def get_name(self): return self.name 288 | def set_name(self, name): self.name = name 289 | def get_member(self): return self.member 290 | def set_member(self, member): self.member = member 291 | def add_member(self, value): self.member.append(value) 292 | def insert_member(self, index, value): self.member[index] = value 293 | def get_kind(self): return self.kind 294 | def set_kind(self, kind): self.kind = kind 295 | def get_refid(self): return self.refid 296 | def set_refid(self, refid): self.refid = refid 297 | def export(self, outfile, level, namespace_='', name_='CompoundType', namespacedef_=''): 298 | showIndent(outfile, level) 299 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 300 | self.exportAttributes(outfile, level, namespace_, name_='CompoundType') 301 | if self.hasContent_(): 302 | outfile.write('>\n') 303 | self.exportChildren(outfile, level + 1, namespace_, name_) 304 | showIndent(outfile, level) 305 | outfile.write('\n' % (namespace_, name_)) 306 | else: 307 | outfile.write(' />\n') 308 | def exportAttributes(self, outfile, level, namespace_='', name_='CompoundType'): 309 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 310 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 311 | def exportChildren(self, outfile, level, namespace_='', name_='CompoundType'): 312 | if self.name is not None: 313 | showIndent(outfile, level) 314 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 315 | for member_ in self.member: 316 | member_.export(outfile, level, namespace_, name_='member') 317 | def hasContent_(self): 318 | if ( 319 | self.name is not None or 320 | self.member is not None 321 | ): 322 | return True 323 | else: 324 | return False 325 | def exportLiteral(self, outfile, level, name_='CompoundType'): 326 | level += 1 327 | self.exportLiteralAttributes(outfile, level, name_) 328 | if self.hasContent_(): 329 | self.exportLiteralChildren(outfile, level, name_) 330 | def exportLiteralAttributes(self, outfile, level, name_): 331 | if self.kind is not None: 332 | showIndent(outfile, level) 333 | outfile.write('kind = "%s",\n' % (self.kind,)) 334 | if self.refid is not None: 335 | showIndent(outfile, level) 336 | outfile.write('refid = %s,\n' % (self.refid,)) 337 | def exportLiteralChildren(self, outfile, level, name_): 338 | showIndent(outfile, level) 339 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 340 | showIndent(outfile, level) 341 | outfile.write('member=[\n') 342 | level += 1 343 | for member in self.member: 344 | showIndent(outfile, level) 345 | outfile.write('model_.member(\n') 346 | member.exportLiteral(outfile, level, name_='member') 347 | showIndent(outfile, level) 348 | outfile.write('),\n') 349 | level -= 1 350 | showIndent(outfile, level) 351 | outfile.write('],\n') 352 | def build(self, node_): 353 | attrs = node_.attributes 354 | self.buildAttributes(attrs) 355 | for child_ in node_.childNodes: 356 | nodeName_ = child_.nodeName.split(':')[-1] 357 | self.buildChildren(child_, nodeName_) 358 | def buildAttributes(self, attrs): 359 | if attrs.get('kind'): 360 | self.kind = attrs.get('kind').value 361 | if attrs.get('refid'): 362 | self.refid = attrs.get('refid').value 363 | def buildChildren(self, child_, nodeName_): 364 | if child_.nodeType == Node.ELEMENT_NODE and \ 365 | nodeName_ == 'name': 366 | name_ = '' 367 | for text__content_ in child_.childNodes: 368 | name_ += text__content_.nodeValue 369 | self.name = name_ 370 | elif child_.nodeType == Node.ELEMENT_NODE and \ 371 | nodeName_ == 'member': 372 | obj_ = MemberType.factory() 373 | obj_.build(child_) 374 | self.member.append(obj_) 375 | # end class CompoundType 376 | 377 | 378 | class MemberType(GeneratedsSuper): 379 | subclass = None 380 | superclass = None 381 | def __init__(self, kind=None, refid=None, name=None): 382 | self.kind = kind 383 | self.refid = refid 384 | self.name = name 385 | def factory(*args_, **kwargs_): 386 | if MemberType.subclass: 387 | return MemberType.subclass(*args_, **kwargs_) 388 | else: 389 | return MemberType(*args_, **kwargs_) 390 | factory = staticmethod(factory) 391 | def get_name(self): return self.name 392 | def set_name(self, name): self.name = name 393 | def get_kind(self): return self.kind 394 | def set_kind(self, kind): self.kind = kind 395 | def get_refid(self): return self.refid 396 | def set_refid(self, refid): self.refid = refid 397 | def export(self, outfile, level, namespace_='', name_='MemberType', namespacedef_=''): 398 | showIndent(outfile, level) 399 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 400 | self.exportAttributes(outfile, level, namespace_, name_='MemberType') 401 | if self.hasContent_(): 402 | outfile.write('>\n') 403 | self.exportChildren(outfile, level + 1, namespace_, name_) 404 | showIndent(outfile, level) 405 | outfile.write('\n' % (namespace_, name_)) 406 | else: 407 | outfile.write(' />\n') 408 | def exportAttributes(self, outfile, level, namespace_='', name_='MemberType'): 409 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 410 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 411 | def exportChildren(self, outfile, level, namespace_='', name_='MemberType'): 412 | if self.name is not None: 413 | showIndent(outfile, level) 414 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 415 | def hasContent_(self): 416 | if ( 417 | self.name is not None 418 | ): 419 | return True 420 | else: 421 | return False 422 | def exportLiteral(self, outfile, level, name_='MemberType'): 423 | level += 1 424 | self.exportLiteralAttributes(outfile, level, name_) 425 | if self.hasContent_(): 426 | self.exportLiteralChildren(outfile, level, name_) 427 | def exportLiteralAttributes(self, outfile, level, name_): 428 | if self.kind is not None: 429 | showIndent(outfile, level) 430 | outfile.write('kind = "%s",\n' % (self.kind,)) 431 | if self.refid is not None: 432 | showIndent(outfile, level) 433 | outfile.write('refid = %s,\n' % (self.refid,)) 434 | def exportLiteralChildren(self, outfile, level, name_): 435 | showIndent(outfile, level) 436 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 437 | def build(self, node_): 438 | attrs = node_.attributes 439 | self.buildAttributes(attrs) 440 | for child_ in node_.childNodes: 441 | nodeName_ = child_.nodeName.split(':')[-1] 442 | self.buildChildren(child_, nodeName_) 443 | def buildAttributes(self, attrs): 444 | if attrs.get('kind'): 445 | self.kind = attrs.get('kind').value 446 | if attrs.get('refid'): 447 | self.refid = attrs.get('refid').value 448 | def buildChildren(self, child_, nodeName_): 449 | if child_.nodeType == Node.ELEMENT_NODE and \ 450 | nodeName_ == 'name': 451 | name_ = '' 452 | for text__content_ in child_.childNodes: 453 | name_ += text__content_.nodeValue 454 | self.name = name_ 455 | # end class MemberType 456 | 457 | 458 | USAGE_TEXT = """ 459 | Usage: python .py [ -s ] 460 | Options: 461 | -s Use the SAX parser, not the minidom parser. 462 | """ 463 | 464 | def usage(): 465 | print USAGE_TEXT 466 | sys.exit(1) 467 | 468 | 469 | def parse(inFileName): 470 | doc = minidom.parse(inFileName) 471 | rootNode = doc.documentElement 472 | rootObj = DoxygenType.factory() 473 | rootObj.build(rootNode) 474 | # Enable Python to collect the space used by the DOM. 475 | doc = None 476 | sys.stdout.write('\n') 477 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 478 | namespacedef_='') 479 | return rootObj 480 | 481 | 482 | def parseString(inString): 483 | doc = minidom.parseString(inString) 484 | rootNode = doc.documentElement 485 | rootObj = DoxygenType.factory() 486 | rootObj.build(rootNode) 487 | # Enable Python to collect the space used by the DOM. 488 | doc = None 489 | sys.stdout.write('\n') 490 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 491 | namespacedef_='') 492 | return rootObj 493 | 494 | 495 | def parseLiteral(inFileName): 496 | doc = minidom.parse(inFileName) 497 | rootNode = doc.documentElement 498 | rootObj = DoxygenType.factory() 499 | rootObj.build(rootNode) 500 | # Enable Python to collect the space used by the DOM. 501 | doc = None 502 | sys.stdout.write('from index import *\n\n') 503 | sys.stdout.write('rootObj = doxygenindex(\n') 504 | rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex") 505 | sys.stdout.write(')\n') 506 | return rootObj 507 | 508 | 509 | def main(): 510 | args = sys.argv[1:] 511 | if len(args) == 1: 512 | parse(args[0]) 513 | else: 514 | usage() 515 | 516 | 517 | 518 | 519 | if __name__ == '__main__': 520 | main() 521 | #import pdb 522 | #pdb.run('main()') 523 | 524 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/run_tests.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 1st parameter is absolute path to component source directory 4 | # 2nd parameter is absolute path to component build directory 5 | # 3rd parameter is path to Python QA directory 6 | 7 | # Note: calling master run_tests.sh in gnuradio core is not strictly 8 | # correct, as it will result in a partially bogus PYTHONPATH, but it 9 | # does make the correct paths in the second half so all is well. 10 | 11 | @PYTHON@ @srcdir@/__init__.py 12 | 13 | # @top_builddir@/run_tests.sh \ 14 | # @abs_top_srcdir@/gnuradio-core \ 15 | # @abs_top_builddir@/gnuradio-core \ 16 | # @srcdir@ 17 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/text.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | """ 22 | Utilities for extracting text from generated classes. 23 | """ 24 | 25 | def is_string(txt): 26 | if isinstance(txt, str): 27 | return True 28 | try: 29 | if isinstance(txt, unicode): 30 | return True 31 | except NameError: 32 | pass 33 | return False 34 | 35 | def description(obj): 36 | if obj is None: 37 | return None 38 | return description_bit(obj).strip() 39 | 40 | def description_bit(obj): 41 | if hasattr(obj, 'content'): 42 | contents = [description_bit(item) for item in obj.content] 43 | result = ''.join(contents) 44 | elif hasattr(obj, 'content_'): 45 | contents = [description_bit(item) for item in obj.content_] 46 | result = ''.join(contents) 47 | elif hasattr(obj, 'value'): 48 | result = description_bit(obj.value) 49 | elif is_string(obj): 50 | return obj 51 | else: 52 | raise StandardError('Expecting a string or something with content, content_ or value attribute') 53 | # If this bit is a paragraph then add one some line breaks. 54 | if hasattr(obj, 'name') and obj.name == 'para': 55 | result += "\n\n" 56 | return result 57 | -------------------------------------------------------------------------------- /docs/doxygen/other/group_defs.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | * \defgroup block GNU Radio GR_AIS C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the GR_AIS GNU Radio 4 | * module are listed here or in the subcategories below. 5 | * 6 | */ 7 | 8 | -------------------------------------------------------------------------------- /docs/doxygen/other/main_page.dox: -------------------------------------------------------------------------------- 1 | /*! \mainpage 2 | 3 | Welcome to the GNU Radio GR_AIS Block 4 | 5 | This is the intro page for the Doxygen manual generated for the GR_AIS 6 | block (docs/doxygen/other/main_page.dox). Edit it to add more detailed 7 | documentation about the new GNU Radio modules contained in this 8 | project. 9 | 10 | */ 11 | -------------------------------------------------------------------------------- /docs/doxygen/swig_doc.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010,2011 Free Software Foundation, Inc. 3 | # 4 | # This file is part of GNU Radio 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | """ 22 | Creates the swig_doc.i SWIG interface file. 23 | Execute using: python swig_doc.py xml_path outputfilename 24 | 25 | The file instructs SWIG to transfer the doxygen comments into the 26 | python docstrings. 27 | 28 | """ 29 | 30 | import sys 31 | 32 | try: 33 | from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base 34 | except ImportError: 35 | from gnuradio.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base 36 | 37 | 38 | def py_name(name): 39 | bits = name.split('_') 40 | return '_'.join(bits[1:]) 41 | 42 | def make_name(name): 43 | bits = name.split('_') 44 | return bits[0] + '_make_' + '_'.join(bits[1:]) 45 | 46 | 47 | class Block(object): 48 | """ 49 | Checks if doxyxml produced objects correspond to a gnuradio block. 50 | """ 51 | 52 | @classmethod 53 | def includes(cls, item): 54 | if not isinstance(item, DoxyClass): 55 | return False 56 | # Check for a parsing error. 57 | if item.error(): 58 | return False 59 | return item.has_member(make_name(item.name()), DoxyFriend) 60 | 61 | 62 | def utoascii(text): 63 | """ 64 | Convert unicode text into ascii and escape quotes. 65 | """ 66 | if text is None: 67 | return '' 68 | out = text.encode('ascii', 'replace') 69 | out = out.replace('"', '\\"') 70 | return out 71 | 72 | 73 | def combine_descriptions(obj): 74 | """ 75 | Combines the brief and detailed descriptions of an object together. 76 | """ 77 | description = [] 78 | bd = obj.brief_description.strip() 79 | dd = obj.detailed_description.strip() 80 | if bd: 81 | description.append(bd) 82 | if dd: 83 | description.append(dd) 84 | return utoascii('\n\n'.join(description)).strip() 85 | 86 | 87 | entry_templ = '%feature("docstring") {name} "{docstring}"' 88 | def make_entry(obj, name=None, templ="{description}", description=None): 89 | """ 90 | Create a docstring entry for a swig interface file. 91 | 92 | obj - a doxyxml object from which documentation will be extracted. 93 | name - the name of the C object (defaults to obj.name()) 94 | templ - an optional template for the docstring containing only one 95 | variable named 'description'. 96 | description - if this optional variable is set then it's value is 97 | used as the description instead of extracting it from obj. 98 | """ 99 | if name is None: 100 | name=obj.name() 101 | if description is None: 102 | description = combine_descriptions(obj) 103 | docstring = templ.format(description=description) 104 | if not docstring: 105 | return '' 106 | return entry_templ.format( 107 | name=name, 108 | docstring=docstring, 109 | ) 110 | 111 | 112 | def make_func_entry(func, name=None, description=None, params=None): 113 | """ 114 | Create a function docstring entry for a swig interface file. 115 | 116 | func - a doxyxml object from which documentation will be extracted. 117 | name - the name of the C object (defaults to func.name()) 118 | description - if this optional variable is set then it's value is 119 | used as the description instead of extracting it from func. 120 | params - a parameter list that overrides using func.params. 121 | """ 122 | if params is None: 123 | params = func.params 124 | params = [prm.declname for prm in params] 125 | if params: 126 | sig = "Params: (%s)" % ", ".join(params) 127 | else: 128 | sig = "Params: (NONE)" 129 | templ = "{description}\n\n" + sig 130 | return make_entry(func, name=name, templ=utoascii(templ), 131 | description=description) 132 | 133 | 134 | def make_class_entry(klass, description=None): 135 | """ 136 | Create a class docstring for a swig interface file. 137 | """ 138 | output = [] 139 | output.append(make_entry(klass, description=description)) 140 | for func in klass.in_category(DoxyFunction): 141 | name = klass.name() + '::' + func.name() 142 | output.append(make_func_entry(func, name=name)) 143 | return "\n\n".join(output) 144 | 145 | 146 | def make_block_entry(di, block): 147 | """ 148 | Create class and function docstrings of a gnuradio block for a 149 | swig interface file. 150 | """ 151 | descriptions = [] 152 | # Get the documentation associated with the class. 153 | class_desc = combine_descriptions(block) 154 | if class_desc: 155 | descriptions.append(class_desc) 156 | # Get the documentation associated with the make function 157 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 158 | make_func_desc = combine_descriptions(make_func) 159 | if make_func_desc: 160 | descriptions.append(make_func_desc) 161 | # Get the documentation associated with the file 162 | try: 163 | block_file = di.get_member(block.name() + ".h", DoxyFile) 164 | file_desc = combine_descriptions(block_file) 165 | if file_desc: 166 | descriptions.append(file_desc) 167 | except base.Base.NoSuchMember: 168 | # Don't worry if we can't find a matching file. 169 | pass 170 | # And join them all together to make a super duper description. 171 | super_description = "\n\n".join(descriptions) 172 | # Associate the combined description with the class and 173 | # the make function. 174 | output = [] 175 | output.append(make_class_entry(block, description=super_description)) 176 | creator = block.get_member(block.name(), DoxyFunction) 177 | output.append(make_func_entry(make_func, description=super_description, 178 | params=creator.params)) 179 | return "\n\n".join(output) 180 | 181 | 182 | def make_swig_interface_file(di, swigdocfilename, custom_output=None): 183 | 184 | output = [""" 185 | /* 186 | * This file was automatically generated using swig_doc.py. 187 | * 188 | * Any changes to it will be lost next time it is regenerated. 189 | */ 190 | """] 191 | 192 | if custom_output is not None: 193 | output.append(custom_output) 194 | 195 | # Create docstrings for the blocks. 196 | blocks = di.in_category(Block) 197 | make_funcs = set([]) 198 | for block in blocks: 199 | try: 200 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 201 | make_funcs.add(make_func.name()) 202 | output.append(make_block_entry(di, block)) 203 | except block.ParsingError: 204 | print('Parsing error for block %s' % block.name()) 205 | 206 | # Create docstrings for functions 207 | # Don't include the make functions since they have already been dealt with. 208 | funcs = [f for f in di.in_category(DoxyFunction) if f.name() not in make_funcs] 209 | for f in funcs: 210 | try: 211 | output.append(make_func_entry(f)) 212 | except f.ParsingError: 213 | print('Parsing error for function %s' % f.name()) 214 | 215 | # Create docstrings for classes 216 | block_names = [block.name() for block in blocks] 217 | klasses = [k for k in di.in_category(DoxyClass) if k.name() not in block_names] 218 | for k in klasses: 219 | try: 220 | output.append(make_class_entry(k)) 221 | except k.ParsingError: 222 | print('Parsing error for class %s' % k.name()) 223 | 224 | # Docstrings are not created for anything that is not a function or a class. 225 | # If this excludes anything important please add it here. 226 | 227 | output = "\n\n".join(output) 228 | 229 | swig_doc = file(swigdocfilename, 'w') 230 | swig_doc.write(output) 231 | swig_doc.close() 232 | 233 | if __name__ == "__main__": 234 | # Parse command line options and set up doxyxml. 235 | err_msg = "Execute using: python swig_doc.py xml_path outputfilename" 236 | if len(sys.argv) != 3: 237 | raise StandardError(err_msg) 238 | xml_path = sys.argv[1] 239 | swigdocfilename = sys.argv[2] 240 | di = DoxyIndex(xml_path) 241 | 242 | # gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined! 243 | # This is presumably a bug in SWIG. 244 | #msg_q = di.get_member(u'gr_msg_queue', DoxyClass) 245 | #insert_tail = msg_q.get_member(u'insert_tail', DoxyFunction) 246 | #delete_head = msg_q.get_member(u'delete_head', DoxyFunction) 247 | output = [] 248 | #output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail')) 249 | #output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head')) 250 | custom_output = "\n\n".join(output) 251 | 252 | # Generate the docstrings interface file. 253 | make_swig_interface_file(di, swigdocfilename, custom_output=custom_output) 254 | -------------------------------------------------------------------------------- /grc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | #install(FILES 21 | # gr_ais_square_ff.xml 22 | # gr_ais_square2_ff.xml 23 | # DESTINATION share/gnuradio/grc/blocks 24 | #) 25 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Install public header files 22 | ######################################################################## 23 | install( 24 | DIRECTORY ${CMAKE_SOURCE_DIR}/include 25 | DESTINATION include/gr_ais 26 | FILES_MATCHING PATTERN "*.h" 27 | ) 28 | -------------------------------------------------------------------------------- /include/ais_extended_lms_dfe_ff.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_AIS_EXTENDED_LMS_DFE_FF_H 2 | #define INCLUDED_AIS_EXTENDED_LMS_DFE_FF_H 3 | 4 | #include 5 | 6 | class ais_extended_lms_dfe_ff; 7 | typedef boost::shared_ptr ais_extended_lms_dfe_ff_sptr; 8 | 9 | ais_extended_lms_dfe_ff_sptr ais_make_extended_lms_dfe_ff (float lambda_ff, float lambda_fb, 10 | unsigned int num_fftaps, unsigned int num_fbtaps); 11 | 12 | /*! 13 | * \brief Least-Mean-Square Decision Feedback Equalizer (float in/out) with reset input and preamble training 14 | * \ingroup eq_blk 15 | */ 16 | class ais_extended_lms_dfe_ff : public gr_sync_block 17 | { 18 | friend ais_extended_lms_dfe_ff_sptr ais_make_extended_lms_dfe_ff (float lambda_ff, float lambda_fb, 19 | unsigned int num_fftaps, unsigned int num_fbtaps); 20 | 21 | float d_lambda_ff; 22 | float d_lambda_fb; 23 | std::vector d_ff_delayline; 24 | std::vector d_fb_delayline; 25 | std::vector d_ff_taps; 26 | std::vector d_fb_taps; 27 | unsigned int d_ff_index; 28 | unsigned int d_fb_index; 29 | unsigned int d_resetcounter; 30 | 31 | ais_extended_lms_dfe_ff (float lambda_ff, float lambda_fb, 32 | unsigned int num_fftaps, unsigned int num_fbtaps); 33 | 34 | void reset(void); 35 | 36 | public: 37 | 38 | int work (int noutput_items, 39 | gr_vector_const_void_star &input_items, 40 | gr_vector_void_star &output_items); 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/ais_freqest.h: -------------------------------------------------------------------------------- 1 | //ais_freqest.h 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2004 Free Software Foundation, Inc. 5 | * 6 | * This file is part of GNU Radio 7 | * 8 | * GNU Radio is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * GNU Radio is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with GNU Radio; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | #ifndef AIS_freqest_H 24 | #define AIS_freqest_H 25 | 26 | #include 27 | 28 | class ais_freqest; 29 | 30 | /* 31 | * We use boost::shared_ptr's instead of raw pointers for all access 32 | * to gr_blocks (and many other data structures). The shared_ptr gets 33 | * us transparent reference counting, which greatly simplifies storage 34 | * management issues. This is especially helpful in our hybrid 35 | * C++ / Python system. 36 | * 37 | * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm 38 | * 39 | * As a convention, the _sptr suffix indicates a boost::shared_ptr 40 | */ 41 | typedef boost::shared_ptr ais_freqest_sptr; 42 | 43 | /*! 44 | * \brief Return a shared_ptr to a new instance of ais_freqest. 45 | * 46 | * To avoid accidental use of raw pointers, ais_freqest's 47 | * constructor is private. ais_make_freqest is the public 48 | * interface for creating new instances. 49 | */ 50 | ais_freqest_sptr ais_make_freqest(int sample_rate, int data_rate, int fftlen); 51 | 52 | /*! 53 | * \brief freqest a packed stream of bits. 54 | * \ingroup block 55 | * 56 | * 57 | * This uses the preferred technique: subclassing gr_sync_block. 58 | */ 59 | class ais_freqest : public gr_sync_block 60 | { 61 | private: 62 | // The friend declaration allows ais_make_freqest to 63 | // access the private constructor. 64 | 65 | friend ais_freqest_sptr ais_make_freqest(int sample_rate, int data_rate, int fftlen); 66 | 67 | ais_freqest(int sample_rate, int data_rate, int fftlen); // private constructor 68 | 69 | unsigned int d_offset; 70 | float d_binsize; 71 | 72 | public: 73 | ~ais_freqest(); // public destructor 74 | 75 | // Where all the action really happens 76 | 77 | int work (int noutput_items, 78 | gr_vector_const_void_star &input_items, 79 | gr_vector_void_star &output_items); 80 | }; 81 | 82 | #endif /* AIS_freqest_H */ 83 | 84 | -------------------------------------------------------------------------------- /include/ais_invert.h: -------------------------------------------------------------------------------- 1 | //ais_invert.h 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2004 Free Software Foundation, Inc. 5 | * 6 | * This file is part of GNU Radio 7 | * 8 | * GNU Radio is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * GNU Radio is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with GNU Radio; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | #ifndef AIS_INVERT_H 24 | #define AIS_INVERT_H 25 | 26 | #include 27 | 28 | class ais_invert; 29 | 30 | /* 31 | * We use boost::shared_ptr's instead of raw pointers for all access 32 | * to gr_blocks (and many other data structures). The shared_ptr gets 33 | * us transparent reference counting, which greatly simplifies storage 34 | * management issues. This is especially helpful in our hybrid 35 | * C++ / Python system. 36 | * 37 | * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm 38 | * 39 | * As a convention, the _sptr suffix indicates a boost::shared_ptr 40 | */ 41 | typedef boost::shared_ptr ais_invert_sptr; 42 | 43 | /*! 44 | * \brief Return a shared_ptr to a new instance of ais_invert. 45 | * 46 | * To avoid accidental use of raw pointers, ais_invert's 47 | * constructor is private. ais_make_invert is the public 48 | * interface for creating new instances. 49 | */ 50 | ais_invert_sptr ais_make_invert(); 51 | 52 | /*! 53 | * \brief invert a packed stream of bits. 54 | * \ingroup block 55 | * 56 | * 57 | * This uses the preferred technique: subclassing gr_sync_block. 58 | */ 59 | class ais_invert : public gr_sync_block 60 | { 61 | private: 62 | // The friend declaration allows ais_make_invert to 63 | // access the private constructor. 64 | 65 | friend ais_invert_sptr ais_make_invert(); 66 | 67 | ais_invert(); // private constructor 68 | 69 | public: 70 | ~ais_invert(); // public destructor 71 | 72 | // Where all the action really happens 73 | 74 | int work (int noutput_items, 75 | gr_vector_const_void_star &input_items, 76 | gr_vector_void_star &output_items); 77 | }; 78 | 79 | #endif /* AIS_INVERT_H */ 80 | 81 | -------------------------------------------------------------------------------- /include/ais_parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2006 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * GNU Radio is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * GNU Radio is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GNU Radio; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef INCLUDED_AIS_PARSE_H 23 | #define INCLUDED_AIS_PARSE_H 24 | 25 | #include 26 | #include 27 | //#include 28 | #include 29 | 30 | class ais_parse; 31 | typedef boost::shared_ptr ais_parse_sptr; 32 | 33 | ais_parse_sptr ais_make_parse(gr_msg_queue_sptr queue, char designator); 34 | 35 | /*! 36 | * \brief ais packetizer/parser 37 | * \ingroup block 38 | */ 39 | 40 | #define FIELD_DELIM ((unsigned char)128) 41 | 42 | class ais_parse : public gr_sync_block 43 | { 44 | private: 45 | // Constructors 46 | friend ais_parse_sptr ais_make_parse(gr_msg_queue_sptr queue, char designator); 47 | ais_parse(gr_msg_queue_sptr queue, char designator); 48 | 49 | std::ostringstream d_payload; //message output 50 | gr_msg_queue_sptr d_queue; // Destination for decoded messages 51 | 52 | char d_designator; 53 | 54 | int d_num_stoplost; 55 | int d_num_startlost; 56 | int d_num_found; 57 | 58 | void parse_data(char *data, int len); 59 | void reverse_bit_order(char *data, int length); 60 | unsigned short crc(char *buffer, unsigned int len); 61 | unsigned long unpack(char *buffer, int start, int length); 62 | char nmea_checksum(std::string buffer); 63 | 64 | public: 65 | int work(int noutput_items, 66 | gr_vector_const_void_star &input_items, 67 | gr_vector_void_star &output_items); 68 | }; 69 | 70 | #endif /* INCLUDED_AIS_PARSE_H */ 71 | -------------------------------------------------------------------------------- /include/ais_unstuff.h: -------------------------------------------------------------------------------- 1 | //ais_unstuff.h 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2004 Free Software Foundation, Inc. 5 | * 6 | * This file is part of GNU Radio 7 | * 8 | * GNU Radio is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * GNU Radio is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with GNU Radio; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | #ifndef AIS_unstuff_H 24 | #define AIS_unstuff_H 25 | 26 | #include 27 | 28 | class ais_unstuff; 29 | 30 | /* 31 | * We use boost::shared_ptr's instead of raw pointers for all access 32 | * to gr_blocks (and many other data structures). The shared_ptr gets 33 | * us transparent reference counting, which greatly simplifies storage 34 | * management issues. This is especially helpful in our hybrid 35 | * C++ / Python system. 36 | * 37 | * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm 38 | * 39 | * As a convention, the _sptr suffix indicates a boost::shared_ptr 40 | */ 41 | typedef boost::shared_ptr ais_unstuff_sptr; 42 | 43 | /*! 44 | * \brief Return a shared_ptr to a new instance of ais_unstuff. 45 | * 46 | * To avoid accidental use of raw pointers, ais_unstuff's 47 | * constructor is private. ais_make_unstuff is the public 48 | * interface for creating new instances. 49 | */ 50 | ais_unstuff_sptr ais_make_unstuff(); 51 | 52 | /*! 53 | * \brief unstuff a packed stream of bits. 54 | * \ingroup block 55 | * 56 | * 57 | * This uses the preferred technique: subclassing gr_block. 58 | */ 59 | class ais_unstuff : public gr_block 60 | { 61 | private: 62 | // The friend declaration allows ais_make_unstuff to 63 | // access the private constructor. 64 | 65 | friend ais_unstuff_sptr ais_make_unstuff(); 66 | 67 | ais_unstuff(); // private constructor 68 | 69 | int d_consecutive; 70 | 71 | public: 72 | ~ais_unstuff(); // public destructor 73 | 74 | // Where all the action really happens 75 | 76 | int general_work (int noutput_items, 77 | gr_vector_int &ninput_items, 78 | gr_vector_const_void_star &input_items, 79 | gr_vector_void_star &output_items); 80 | 81 | void forecast (int noutput_items, 82 | gr_vector_int &ninput_items_required); 83 | }; 84 | 85 | #endif /* AIS_unstuff_H */ 86 | 87 | -------------------------------------------------------------------------------- /include/gr_ais_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * GNU Radio is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * GNU Radio is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GNU Radio; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef INCLUDED_GR_AIS_API_H 23 | #define INCLUDED_GR_AIS_API_H 24 | 25 | #include 26 | 27 | #ifdef gnuradio_gr_ais_EXPORTS 28 | # define GR_AIS_API __GR_ATTR_EXPORT 29 | #else 30 | # define GR_AIS_API __GR_ATTR_IMPORT 31 | #endif 32 | 33 | #endif /* INCLUDED_GR_AIS_API_H */ 34 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Setup library 22 | ######################################################################## 23 | include(GrPlatform) #define LIB_SUFFIX 24 | 25 | add_library(gnuradio-gr_ais SHARED ais_extended_lms_dfe_ff.cc ais_freqest.cc ais_invert.cc ais_parse.cc ais_unstuff.cc) 26 | target_link_libraries(gnuradio-gr_ais ${Boost_LIBRARIES} ${GRUEL_LIBRARIES} ${GNURADIO_CORE_LIBRARIES}) 27 | set_target_properties(gnuradio-gr_ais PROPERTIES DEFINE_SYMBOL "gnuradio_gr_ais_EXPORTS") 28 | 29 | ######################################################################## 30 | # Install built library files 31 | ######################################################################## 32 | install(TARGETS gnuradio-gr_ais 33 | LIBRARY DESTINATION lib${LIB_SUFFIX} # .so/.dylib file 34 | ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file 35 | RUNTIME DESTINATION bin # .dll file 36 | ) 37 | 38 | ######################################################################## 39 | # Build and register unit test 40 | ######################################################################## 41 | #find_package(Boost COMPONENTS unit_test_framework) 42 | 43 | #include(GrTest) 44 | #set(GR_TEST_TARGET_DEPS gnuradio-gr_ais) 45 | #turn each test cpp file into an executable with an int main() function 46 | #add_definitions(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) 47 | 48 | #add_executable(qa_gr_ais_square_ff qa_gr_ais_square_ff.cc) 49 | #target_link_libraries(qa_gr_ais_square_ff gnuradio-gr_ais ${Boost_LIBRARIES}) 50 | #GR_ADD_TEST(qa_gr_ais_square_ff qa_gr_ais_square_ff) 51 | 52 | #add_executable(qa_gr_ais_square2_ff qa_gr_ais_square2_ff.cc) 53 | #target_link_libraries(qa_gr_ais_square2_ff gnuradio-gr_ais ${Boost_LIBRARIES}) 54 | #GR_ADD_TEST(qa_gr_ais_square2_ff qa_gr_ais_square2_ff) 55 | -------------------------------------------------------------------------------- /lib/ais_extended_lms_dfe_ff.cc: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include "ais_extended_lms_dfe_ff.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | float 12 | slice(float val) 13 | { 14 | if (val>0) 15 | return 1; 16 | else 17 | return -1; 18 | } 19 | 20 | GR_AIS_API ais_extended_lms_dfe_ff_sptr 21 | ais_make_extended_lms_dfe_ff (float lambda_ff, float lambda_fb, 22 | unsigned int num_fftaps, unsigned int num_fbtaps) 23 | { 24 | return ais_extended_lms_dfe_ff_sptr (new ais_extended_lms_dfe_ff (lambda_ff,lambda_fb,num_fftaps,num_fbtaps)); 25 | } 26 | 27 | ais_extended_lms_dfe_ff::ais_extended_lms_dfe_ff (float lambda_ff, float lambda_fb , 28 | unsigned int num_fftaps, unsigned int num_fbtaps) 29 | : gr_sync_block ("ais_extended_lms_dfe_ff", 30 | gr_make_io_signature2 (2, 2, sizeof (float), sizeof(char)), 31 | gr_make_io_signature (1, 1, sizeof (float))), 32 | d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), 33 | d_ff_delayline(gr_rounduppow2(num_fftaps)), 34 | d_fb_delayline(gr_rounduppow2(num_fbtaps)), 35 | d_ff_taps(num_fftaps), d_fb_taps(num_fbtaps), 36 | d_ff_index(0), d_fb_index(0), d_resetcounter(0) 37 | { 38 | gr_zero_vector(d_ff_taps); 39 | d_ff_taps [d_ff_taps.size()/2] = 1; 40 | 41 | gr_zero_vector(d_fb_taps); 42 | gr_zero_vector(d_ff_delayline); 43 | gr_zero_vector(d_fb_delayline); 44 | 45 | set_output_multiple(300); 46 | } 47 | 48 | void ais_extended_lms_dfe_ff::reset(void) 49 | { 50 | // d_ff_index = 0; 51 | // d_fb_index = 0; 52 | 53 | gr_zero_vector(d_ff_taps); 54 | d_ff_taps[d_ff_taps.size()/2] = 1; 55 | 56 | gr_zero_vector(d_fb_taps); 57 | gr_zero_vector(d_ff_delayline); 58 | gr_zero_vector(d_fb_delayline); 59 | 60 | d_ff_index = 0; 61 | d_fb_index = 0; 62 | 63 | d_resetcounter = 0; 64 | } 65 | 66 | int 67 | ais_extended_lms_dfe_ff::work (int noutput_items, 68 | gr_vector_const_void_star &input_items, 69 | gr_vector_void_star &output_items) 70 | { 71 | const float *iptr = (const float *) input_items[0]; 72 | const char *i2ptr = (const char *) input_items[1]; 73 | 74 | float *optr = (float *) output_items[0]; 75 | 76 | float acc, decision, error; 77 | unsigned int i; 78 | 79 | unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 80 | unsigned int fb_mask = d_fb_delayline.size() - 1; 81 | 82 | int size = noutput_items; 83 | while(size-- > 0) { 84 | 85 | if((*i2ptr++ & 0x02) && (d_resetcounter > 50)) { 86 | if(size < 150) { 87 | //printf("Returning, not enough to work with\n"); 88 | return noutput_items-size; //don't have enough to work with for an entire packet so wait for the next one 89 | } 90 | reset(); //if the correlator bit (bit 1/LSB-1) is set, reset taps to 0 91 | 92 | //now we train the DFE by looping through the first 150 bits a dozen times or so. 93 | 94 | for(int k = 0; k < 12; k++) { //train 12 times 95 | const float *iptr_train = iptr; //a temporary input pointer to train with 96 | while((iptr_train - iptr) < 150) { 97 | acc = 0; 98 | d_ff_delayline[d_ff_index] = *iptr_train++; 99 | 100 | // Compute output 101 | for (i=0; i < d_ff_taps.size(); i++) 102 | acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i]; 103 | 104 | for (i=0; i < d_fb_taps.size(); i++) 105 | acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i]; 106 | 107 | decision = slice(acc); 108 | error = decision - acc; 109 | 110 | // Update taps 111 | for (i=0; i < d_ff_taps.size(); i++) 112 | d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask]; 113 | 114 | for (i=0; i < d_fb_taps.size(); i++) 115 | d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask]; 116 | 117 | d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index 118 | d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index 119 | 120 | d_fb_delayline[d_fb_index] = decision; // Save decision in feedback 121 | } 122 | } 123 | //printf("Resetting DFE\n"); 124 | } 125 | 126 | d_resetcounter++; 127 | 128 | acc = 0; 129 | d_ff_delayline[d_ff_index] = *iptr++; 130 | 131 | // Compute output 132 | for (i=0; i < d_ff_taps.size(); i++) 133 | acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i]; 134 | 135 | for (i=0; i < d_fb_taps.size(); i++) 136 | acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i]; 137 | 138 | decision = slice(acc); 139 | error = decision - acc; 140 | 141 | // Update taps 142 | for (i=0; i < d_ff_taps.size(); i++) 143 | d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask]; 144 | 145 | for (i=0; i < d_fb_taps.size(); i++) 146 | d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask]; 147 | 148 | d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index 149 | d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index 150 | 151 | d_fb_delayline[d_fb_index] = decision; // Save decision in feedback 152 | 153 | *optr++ = acc; // Output decision 154 | } 155 | 156 | if (0){ 157 | std::cout << "FF Taps\t"; 158 | for(i=0;i 34 | #include 35 | #include 36 | 37 | /* 38 | * Create a new instance of ais_freqest and return 39 | * a boost shared_ptr. This is effectively the public constructor. 40 | */ 41 | GR_AIS_API ais_freqest_sptr ais_make_freqest(int sample_rate, int data_rate, int fftlen) 42 | { 43 | return ais_freqest_sptr (new ais_freqest (sample_rate, data_rate, fftlen)); 44 | } 45 | 46 | /* 47 | * Specify constraints on number of input and output streams. 48 | * This info is used to construct the input and output signatures 49 | * (2nd & 3rd args to gr_block's constructor). The input and 50 | * output signatures are used by the runtime system to 51 | * check that a valid number and type of inputs and outputs 52 | * are connected to this block. In this case, we accept 53 | * only 1 input and 1 output. 54 | */ 55 | static const int MIN_IN = 1; // mininum number of input streams 56 | static const int MAX_IN = 1; // maximum number of input streams 57 | static const int MIN_OUT = 1; // minimum number of output streams 58 | static const int MAX_OUT = 1; // maximum number of output streams 59 | 60 | /* 61 | * The private constructor 62 | */ 63 | ais_freqest::ais_freqest (int sample_rate, int data_rate, int fftlen) 64 | : gr_sync_block ("freqest", 65 | gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex) * fftlen), 66 | gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (float))) 67 | { 68 | //the FFT width is equal to the sample rate 69 | //the FFT bin size is equal to the FFT width divided by the number of bins 70 | //the offset is equal to the number of bins times (the data rate / the sample rate) 71 | 72 | d_offset = fftlen * (float(data_rate) / float(sample_rate)); 73 | d_binsize = float(sample_rate) / float(fftlen); 74 | 75 | // printf("Offset: %i, bin size: %f\n", d_offset, d_binsize); 76 | } 77 | 78 | /* 79 | * Our virtual destructor. 80 | */ 81 | ais_freqest::~ais_freqest () 82 | { 83 | // nothing else required in this example 84 | } 85 | 86 | int 87 | ais_freqest::work (int noutput_items, 88 | gr_vector_const_void_star &input_items, 89 | gr_vector_void_star &output_items) 90 | { 91 | 92 | const gr_complex *in = (const gr_complex *) input_items[0]; 93 | float *out = (float *) output_items[0]; 94 | 95 | unsigned int fftlen = input_signature()->sizeof_stream_item(0) / sizeof(gr_complex); 96 | 97 | float maxenergy = 0; 98 | unsigned int maxpos = 0; 99 | float currentenergy; 100 | 101 | //you are responsible for organizing the vector 102 | for (int i = 0; i < noutput_items; i++){ 103 | //for each requested output item 104 | maxenergy = 0; 105 | for(unsigned int j = 0; j < fftlen - d_offset; j++) { 106 | //over the entire fft up until the right side of the "window" butts up against the end 107 | currentenergy = std::abs(in[i*fftlen+j]) + std::abs(in[i*fftlen+j+d_offset]); //sum of the two bins at -datarate/2 and +datarate/2 108 | if(currentenergy > maxenergy) { 109 | maxenergy = currentenergy; 110 | maxpos = j + d_offset/2; //add the offset to find the center position 111 | } 112 | } 113 | //now maxpos contains the center bin, and we must translate that to a frequency offset 114 | out[i] = (float(maxpos) - fftlen/2) * d_binsize/2; //subtract fftlen/2 to center the complex FFT around 0 115 | // printf("maxpos is %u\n", maxpos); 116 | } 117 | 118 | // Tell runtime system how many output items we produced. 119 | return noutput_items; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /lib/ais_invert.cc: -------------------------------------------------------------------------------- 1 | //ais_invert.cc 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2004 Free Software Foundation, Inc. 5 | * 6 | * This file is part of GNU Radio 7 | * 8 | * GNU Radio is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * GNU Radio is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with GNU Radio; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | /* 25 | * config.h is generated by configure. It contains the results 26 | * of probing for features, options etc. It should be the first 27 | * file included in your .cc file. 28 | */ 29 | #ifdef HAVE_CONFIG_H 30 | #include "config.h" 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | /* 38 | * Create a new instance of ais_invert and return 39 | * a boost shared_ptr. This is effectively the public constructor. 40 | */ 41 | GR_AIS_API ais_invert_sptr ais_make_invert() 42 | { 43 | return ais_invert_sptr (new ais_invert ()); 44 | } 45 | 46 | /* 47 | * Specify constraints on number of input and output streams. 48 | * This info is used to construct the input and output signatures 49 | * (2nd & 3rd args to gr_block's constructor). The input and 50 | * output signatures are used by the runtime system to 51 | * check that a valid number and type of inputs and outputs 52 | * are connected to this block. In this case, we accept 53 | * only 1 input and 1 output. 54 | */ 55 | static const int MIN_IN = 1; // mininum number of input streams 56 | static const int MAX_IN = 1; // maximum number of input streams 57 | static const int MIN_OUT = 1; // minimum number of output streams 58 | static const int MAX_OUT = 1; // maximum number of output streams 59 | 60 | /* 61 | * The private constructor 62 | */ 63 | ais_invert::ais_invert () 64 | : gr_sync_block ("invert", 65 | gr_make_io_signature (MIN_IN, MAX_IN, sizeof (char)), 66 | gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (char))) 67 | { 68 | // nothing else required in this example 69 | } 70 | 71 | /* 72 | * Our virtual destructor. 73 | */ 74 | ais_invert::~ais_invert () 75 | { 76 | // nothing else required in this example 77 | } 78 | 79 | int 80 | ais_invert::work (int noutput_items, 81 | gr_vector_const_void_star &input_items, 82 | gr_vector_void_star &output_items) 83 | { 84 | const char *in = (const char *) input_items[0]; 85 | char *out = (char *) output_items[0]; 86 | 87 | for (int i = 0; i < noutput_items; i++){ 88 | if (in[i] == 1) out[i] = 0; 89 | else if (in[i] == 0) out[i] = 1; 90 | // else printf("Non-binary input to invert()\n"); //should probably flag an error somewhere 91 | } 92 | 93 | // Tell runtime system how many output items we produced. 94 | return noutput_items; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /lib/ais_parse.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2004,2006,2007 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * GNU Radio is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * GNU Radio is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GNU Radio; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define VERBOSE 0 36 | 37 | GR_AIS_API ais_parse_sptr ais_make_parse(gr_msg_queue_sptr queue, char designator) 38 | { 39 | return ais_parse_sptr(new ais_parse(queue, designator)); 40 | } 41 | 42 | ais_parse::ais_parse(gr_msg_queue_sptr queue, char designator) : 43 | gr_sync_block("parse", 44 | gr_make_io_signature(1, 1, sizeof(char)), 45 | gr_make_io_signature(0, 0, 0)), 46 | d_queue(queue), 47 | d_designator(designator) 48 | { 49 | d_num_stoplost = 0; 50 | d_num_startlost = 0; 51 | d_num_found = 0; 52 | set_output_multiple(1000); 53 | } 54 | 55 | int ais_parse::work(int noutput_items, 56 | gr_vector_const_void_star &input_items, 57 | gr_vector_void_star &output_items) 58 | { 59 | const char *in = (const char *) input_items[0]; 60 | 61 | int size = noutput_items - 500; //we need to be able to look at least this far forward 62 | if(size <= 0) return 0; 63 | 64 | //look ma, no state machine 65 | //instead of iterating through in[] looking for things, we'll just pull up all the start/stop tags and use those to look for packets 66 | std::vector preamble_tags, start_tags, end_tags; 67 | uint64_t abs_sample_cnt = nitems_read(0); 68 | get_tags_in_range(preamble_tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::pmt_string_to_symbol("ais_preamble")); 69 | if(preamble_tags.size() == 0) return size; //sad trombone 70 | 71 | //look for start & end tags within a reasonable range 72 | uint64_t preamble_mark = preamble_tags[0].offset; 73 | if(VERBOSE) std::cout << "Found a preamble at " << preamble_mark << std::endl; 74 | 75 | //now look for a start tag within reasonable range of the preamble 76 | get_tags_in_range(start_tags, 0, preamble_mark, preamble_mark + 30, pmt::pmt_string_to_symbol("ais_frame")); 77 | if(start_tags.size() == 0) return preamble_mark + 30 - abs_sample_cnt; //nothing here, move on (should update d_num_startlost) 78 | uint64_t start_mark = start_tags[0].offset; 79 | if(VERBOSE) std::cout << "Found a start tag at " << start_mark << std::endl; 80 | 81 | //now look for an end tag within reasonable range of the preamble 82 | get_tags_in_range(end_tags, 0, start_mark + 184, start_mark + 450, pmt::pmt_string_to_symbol("ais_frame")); 83 | if(end_tags.size() == 0) return preamble_mark + 450 - abs_sample_cnt; //should update d_num_stoplost 84 | uint64_t end_mark = end_tags[0].offset; 85 | if(VERBOSE) std::cout << "Found an end tag at " << end_mark << std::endl; 86 | 87 | //now we've got a valid, framed packet 88 | uint64_t datalen = end_mark - start_mark - 8; //includes CRC, discounts end of frame marker 89 | if(VERBOSE) std::cout << "Found packet with length " << datalen << std::endl; 90 | char *pkt = new char[datalen]; 91 | 92 | memcpy(pkt, &in[start_mark-abs_sample_cnt], datalen); 93 | parse_data(pkt, datalen); 94 | delete(pkt); 95 | return end_mark - abs_sample_cnt; 96 | } 97 | 98 | void ais_parse::parse_data(char *data, int len) 99 | { 100 | d_payload.str(""); 101 | 102 | char asciidata[255]; //168/6 bits per ascii char 103 | reverse_bit_order(data, len); //the AIS standard has bits come in backwards for some inexplicable reason 104 | if(crc(data, len)) { 105 | if(VERBOSE) std::cout << "Failed CRC!" << std::endl; 106 | return; //don't make a message if crc fails 107 | } 108 | 109 | len -= 16; //strip off CRC 110 | 111 | for(int i = 0; i < len/6; i++) { 112 | asciidata[i] = unpack(data, i*6, 6); 113 | if(asciidata[i] > 39) asciidata[i] += 8; 114 | asciidata[i] += 48; 115 | } 116 | 117 | //hey just a note, NMEA sentences are limited to 82 characters. the 448-bit long AIS messages end up longer than 82 encoded chars. 118 | //so technically, the below is not valid as it does not split long sentences for you. the upside is that ESR's GPSD (recommended for this use) 119 | //ignores this length restriction and parses them anyway. but this might bite you if you use this program with other parsers. 120 | //you should probably write something to split the sentences here. shouldn't be hard at all. 121 | //if(debug) d_payload << "BAD PACKET: "; 122 | d_payload << "!AIVDM,1,1,," << d_designator << ","; 123 | for(int i = 0; i < len/6; i++) d_payload << asciidata[i]; 124 | d_payload << ",0"; //number of bits to fill out 6-bit boundary 125 | 126 | char checksum = nmea_checksum(std::string(d_payload.str())); 127 | d_payload << "*" << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << int(checksum); 128 | 129 | //ptooie 130 | gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str())); 131 | d_queue->handle(msg); 132 | } 133 | 134 | unsigned long ais_parse::unpack(char *buffer, int start, int length) 135 | { 136 | unsigned long ret = 0; 137 | for(int i = start; i < (start+length); i++) { 138 | ret <<= 1; 139 | ret |= (buffer[i] & 0x01); 140 | } 141 | return ret; 142 | } 143 | 144 | void ais_parse::reverse_bit_order(char *data, int length) 145 | { 146 | int tmp = 0; 147 | for(int i = 0; i < length/8; i++) { 148 | for(int j = 0; j < 4; j++) { 149 | tmp = data[i*8 + j]; 150 | data[i*8 + j] = data[i*8 + 7-j]; 151 | data[i*8 + 7-j] = tmp; 152 | } 153 | } 154 | } 155 | 156 | char ais_parse::nmea_checksum(std::string buffer) 157 | { 158 | unsigned int i = 0; 159 | char sum = 0x00; 160 | if(buffer[0] == '!') i++; 161 | for(; i < buffer.length(); i++) sum ^= buffer[i]; 162 | return sum; 163 | } 164 | 165 | unsigned short ais_parse::crc(char *buffer, unsigned int len) // Calculates CRC-checksum from unpacked data 166 | { 167 | static const uint16_t crc_itu16_table[] = 168 | { 169 | 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 170 | 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 171 | 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 172 | 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 173 | 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, 174 | 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, 175 | 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, 176 | 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, 177 | 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, 178 | 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 179 | 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 180 | 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 181 | 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 182 | 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 183 | 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, 184 | 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, 185 | 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, 186 | 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, 187 | 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 188 | 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 189 | 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 190 | 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 191 | 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, 192 | 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, 193 | 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, 194 | 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, 195 | 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, 196 | 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 197 | 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 198 | 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 199 | 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 200 | 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 201 | }; 202 | 203 | unsigned short crc=0xffff; 204 | int i = 0; 205 | 206 | int datalen = len/8; 207 | 208 | char data[256]; 209 | for(int j=0;j> 8) ^ crc_itu16_table[(crc ^ data[i]) & 0xFF]; 216 | 217 | return (crc & 0xFFFF) != 0xF0B8; 218 | } 219 | -------------------------------------------------------------------------------- /lib/ais_unstuff.cc: -------------------------------------------------------------------------------- 1 | //ais_unstuff.cc 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2004 Free Software Foundation, Inc. 5 | * 6 | * This file is part of GNU Radio 7 | * 8 | * GNU Radio is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * GNU Radio is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with GNU Radio; see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, 21 | * Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | /* 25 | * config.h is generated by configure. It contains the results 26 | * of probing for features, options etc. It should be the first 27 | * file included in your .cc file. 28 | */ 29 | #ifdef HAVE_CONFIG_H 30 | #include "config.h" 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | /* 38 | * Create a new instance of ais_unstuff and return 39 | * a boost shared_ptr. This is effectively the public constructor. 40 | */ 41 | GR_AIS_API ais_unstuff_sptr ais_make_unstuff() 42 | { 43 | return ais_unstuff_sptr (new ais_unstuff ()); 44 | } 45 | 46 | /* 47 | * Specify constraints on number of input and output streams. 48 | * This info is used to construct the input and output signatures 49 | * (2nd & 3rd args to gr_block's constructor). The input and 50 | * output signatures are used by the runtime system to 51 | * check that a valid number and type of inputs and outputs 52 | * are connected to this block. In this case, we accept 53 | * only 1 input and 1 output. 54 | */ 55 | static const int MIN_IN = 1; // mininum number of input streams 56 | static const int MAX_IN = 1; // maximum number of input streams 57 | static const int MIN_OUT = 1; // minimum number of output streams 58 | static const int MAX_OUT = 1; // maximum number of output streams 59 | 60 | /* 61 | * The private constructor 62 | */ 63 | ais_unstuff::ais_unstuff () 64 | : gr_block ("unstuff", 65 | gr_make_io_signature (MIN_IN, MAX_IN, sizeof (char)), 66 | gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (char))) 67 | { 68 | set_relative_rate((double)1.0); 69 | d_consecutive = 0; 70 | set_output_multiple(1000); 71 | //printf("Calling constructor\n"); 72 | } 73 | 74 | /* 75 | * Our virtual destructor. 76 | */ 77 | ais_unstuff::~ais_unstuff () 78 | { 79 | // nothing else required in this example 80 | } 81 | 82 | void ais_unstuff::forecast (int noutput_items, 83 | gr_vector_int &ninput_items_required) //estimate number of input samples required for noutput_items samples 84 | { 85 | int size = noutput_items + 2*(noutput_items / 256); //on average 86 | 87 | ninput_items_required[0] = size; 88 | } 89 | 90 | 91 | //so is this is gonna unstuff the start and stop codes? nooooo, because those have a following '1'. 92 | int 93 | ais_unstuff::general_work (int noutput_items, 94 | gr_vector_int &ninput_items, 95 | gr_vector_const_void_star &input_items, 96 | gr_vector_void_star &output_items) 97 | { 98 | const char *in = (const char *) input_items[0]; 99 | char *out = (char *) output_items[0]; 100 | 101 | int j = 0; 102 | int i = 0; 103 | 104 | while(j < noutput_items && i < ninput_items[0]){ 105 | if(in[i] & 0x01) {//if bit 0 is set (the data bit) 106 | d_consecutive++; 107 | } else { 108 | if(d_consecutive == 5) { 109 | i++; 110 | } 111 | d_consecutive = 0; 112 | } 113 | out[j++] = in[i++]; 114 | } 115 | 116 | consume_each(i); //tell gnuradio how many input items we used 117 | // Tell runtime system how many output items we produced. 118 | return j; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Include python install macros 22 | ######################################################################## 23 | include(GrPython) 24 | if(NOT PYTHONINTERP_FOUND) 25 | return() 26 | endif() 27 | 28 | ######################################################################## 29 | # Install python sources 30 | ######################################################################## 31 | GR_PYTHON_INSTALL( 32 | FILES 33 | __init__.py 34 | ais_demod.py 35 | fsm_utils.py 36 | gmsk_sync.py 37 | DESTINATION ${GR_PYTHON_DIR}/gr_ais 38 | ) 39 | 40 | ######################################################################## 41 | # Handle the unit tests 42 | ######################################################################## 43 | #include(GrTest) 44 | 45 | #set(GR_TEST_TARGET_DEPS gnuradio-gr_ais) 46 | #set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) 47 | #GR_ADD_TEST(qa_gr_ais ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_ais.py) 48 | -------------------------------------------------------------------------------- /python/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008,2009 Free Software Foundation, Inc. 3 | # 4 | # This application is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 3, or (at your option) 7 | # any later version. 8 | # 9 | # This application is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | # The presence of this file turns this directory into a Python package 20 | 21 | ''' 22 | This is the GNU Radio GR_AIS module. Place your Python package 23 | description here (python/__init__.py). 24 | ''' 25 | 26 | # ---------------------------------------------------------------- 27 | # Temporary workaround for ticket:181 (swig+python problem) 28 | import sys 29 | _RTLD_GLOBAL = 0 30 | try: 31 | from dl import RTLD_GLOBAL as _RTLD_GLOBAL 32 | except ImportError: 33 | try: 34 | from DLFCN import RTLD_GLOBAL as _RTLD_GLOBAL 35 | except ImportError: 36 | pass 37 | 38 | if _RTLD_GLOBAL != 0: 39 | _dlopenflags = sys.getdlopenflags() 40 | sys.setdlopenflags(_dlopenflags|_RTLD_GLOBAL) 41 | # ---------------------------------------------------------------- 42 | 43 | 44 | # import swig generated symbols into the gr_ais namespace 45 | from gr_ais_swig import * 46 | 47 | # import any pure python here 48 | # 49 | 50 | # ---------------------------------------------------------------- 51 | # Tail of workaround 52 | if _RTLD_GLOBAL != 0: 53 | sys.setdlopenflags(_dlopenflags) # Restore original flags 54 | # ---------------------------------------------------------------- 55 | -------------------------------------------------------------------------------- /python/ais_demod.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #ais_demod.py 3 | #implements a hierarchical class to demodulate GMSK packets as per AIS, including differential decoding and bit inversion for NRZI. 4 | #does not unstuff bits 5 | 6 | #modified 4/29/10 to include frequency estimation to center signals at baseband 7 | #eventually will do coherent demodulation 8 | #right now, it does coherent demod, but it's crippled for two reasons. 9 | #first, there's no "reset" input on the gr-trellis VA, so the algorithm doesn't get properly initialized at the start of a packet 10 | #second, there's no provision for phase estimation, so the combined trellis assumes each packet starts at phase=0. 11 | #sometimes it'll cope with this, but it loses a lot of packets 12 | 13 | from gnuradio import gr, gru, blks2 14 | from gnuradio import eng_notation 15 | import gr_ais_swig as ais 16 | from gnuradio import trellis 17 | from gnuradio import window 18 | from gnuradio import digital 19 | import fsm_utils 20 | import gmsk_sync 21 | 22 | #from gmskenhanced import gmsk_demod 23 | #from gmskmod import gmsk_demod 24 | import numpy 25 | import scipy 26 | import scipy.stats 27 | import math 28 | 29 | #make_gmsk uses make_cpm_signals to create GMSK signals for a given samples per symbol and BT. 30 | #based on (copied from) Achilleas Anastasopoulos's test_cpm.py 31 | #uses his method of CPM decomposition 32 | #returns an FSM, a constellation, the required matched filters, N (the length of the required trellis), and f0T (the memoryless modulation component frequency) 33 | def make_gmsk(samples_per_symbol, BT): 34 | #M, K, P, h, L are fixed for GMSK 35 | M = 2 #number of bits per symbol 36 | K = 1 37 | P = 2 #h=K/P, K and P are relatively prime 38 | h = (1.0*K)/P 39 | L = 3 40 | Q = samples_per_symbol 41 | frac = 0.99 #fractional energy component deemed necessary to consider in the trellis, for finding dimensionality 42 | 43 | fsm = trellis.fsm(P, M, L) 44 | 45 | tt=numpy.arange(0,L*Q)/(1.0*Q)-L/2.0 46 | p=(0.5*scipy.stats.erfc(2*math.pi*BT*(tt-0.5)/math.sqrt(math.log(2.0))/math.sqrt(2.0))-0.5*scipy.stats.erfc(2*math.pi*BT*(tt+0.5)/math.sqrt(math.log(2.0))/math.sqrt(2.0)))/2.0 47 | p=p/sum(p)*Q/2.0 48 | q=numpy.cumsum(p)/Q 49 | q=q/q[-1]/2.0 50 | (f0T,SS,S,F,Sf,Ff,N) = fsm_utils.make_cpm_signals(K,P,M,L,q,frac) 51 | constellation = numpy.reshape(numpy.transpose(Sf),N*fsm.O()) 52 | Ffa = numpy.insert(Ff,Q,numpy.zeros(N),axis=0) 53 | MF = numpy.fliplr(numpy.transpose(Ffa)) 54 | 55 | return (fsm, constellation, MF, N, f0T) 56 | 57 | def gcd(a, b): 58 | if a > b: a, b = b, a 59 | while a > 0: a, b = (b % a), a 60 | return b 61 | 62 | class ais_demod(gr.hier_block2): 63 | def __init__(self, options): 64 | 65 | gr.hier_block2.__init__(self, "ais_demod", 66 | gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature 67 | gr.io_signature(1, 1, gr.sizeof_char)) # Output signature 68 | 69 | self._samples_per_symbol = options.samples_per_symbol 70 | self._bits_per_sec = options.bits_per_sec 71 | self._samplerate = self._samples_per_symbol * self._bits_per_sec 72 | self._gain_mu = options.gain_mu 73 | self._mu = options.mu 74 | self._omega_relative_limit = options.omega_relative_limit 75 | self.fftlen = options.fftlen 76 | 77 | #right now we are going to hardcode the different options for VA mode here. later on we can use configurable options 78 | samples_per_symbol_viterbi = 2 79 | bits_per_symbol = 2 80 | samples_per_symbol = 6 81 | samples_per_symbol_clockrec = samples_per_symbol / bits_per_symbol 82 | BT = 0.4 83 | data_rate = 9600.0 84 | samp_rate = options.samp_rate 85 | 86 | self.gmsk_sync = gmsk_sync.square_and_fft_sync(self._samplerate, self._bits_per_sec, self.fftlen) 87 | 88 | if(options.viterbi is True): 89 | #calculate the required decimation and interpolation to achieve the desired samples per symbol 90 | denom = gcd(data_rate*samples_per_symbol, samp_rate) 91 | cr_interp = int(data_rate*samples_per_symbol/denom) 92 | cr_decim = int(samp_rate/denom) 93 | self.resample = blks2.rational_resampler_ccc(cr_interp, cr_decim) 94 | #here we take a different tack and use A.A.'s CPM decomposition technique 95 | self.clockrec = gr.clock_recovery_mm_cc(samples_per_symbol_clockrec, 0.005*0.005*0.25, 0.5, 0.005, 0.0005) #might have to futz with the max. deviation 96 | (fsm, constellation, MF, N, f0T) = make_gmsk(samples_per_symbol_viterbi, BT) #calculate the decomposition required for demodulation 97 | self.costas = gr.costas_loop_cc(0.015, 0.015*0.015*0.25, 100e-6, -100e-6, 4) #does fine freq/phase synchronization. should probably calc the coeffs instead of hardcode them. 98 | self.streams2stream = gr.streams_to_stream(int(gr.sizeof_gr_complex*1), int(N)) 99 | self.mf0 = gr.fir_filter_ccc(samples_per_symbol_viterbi, MF[0].conjugate()) #two matched filters for decomposition 100 | self.mf1 = gr.fir_filter_ccc(samples_per_symbol_viterbi, MF[1].conjugate()) 101 | self.fo = gr.sig_source_c(samples_per_symbol_viterbi, gr.GR_COS_WAVE, -f0T, 1, 0) #the memoryless modulation component of the decomposition 102 | self.fomult = gr.multiply_cc(1) 103 | self.trellis = trellis.viterbi_combined_cb(fsm, int(data_rate), -1, -1, int(N), constellation, trellis.TRELLIS_EUCLIDEAN) #the actual Viterbi decoder 104 | 105 | else: 106 | #this is probably not optimal and someone who knows what they're doing should correct me 107 | self.datafiltertaps = gr.firdes.root_raised_cosine(10, #gain 108 | self._samplerate*32, #sample rate 109 | self._bits_per_sec, #symbol rate 110 | 0.4, #alpha, same as BT? 111 | 50*32) #no. of taps 112 | 113 | self.datafilter = gr.fir_filter_fff(1, self.datafiltertaps) 114 | 115 | sensitivity = (math.pi / 2) / self._samples_per_symbol 116 | self.demod = gr.quadrature_demod_cf(sensitivity) #param is gain 117 | 118 | #self.clockrec = digital.clock_recovery_mm_ff(self._samples_per_symbol,0.25*self._gain_mu*self._gain_mu,self._mu,self._gain_mu,self._omega_relative_limit) 119 | self.clockrec = gr.pfb_clock_sync_ccf(self._samples_per_symbol, 0.04, self.datafiltertaps, 32, 0, 1.15) 120 | self.tcslicer = digital.digital.binary_slicer_fb() 121 | # self.dfe = digital.digital.lms_dd_equalizer_cc( 122 | # 32, 123 | # 0.005, 124 | # 1, 125 | # digital.digital.constellation_bpsk() 126 | # ) 127 | 128 | # self.delay = gr.delay(gr.sizeof_float, 64 + 16) #the correlator delays 64 bits, and the LMS delays some as well. 129 | self.slicer = digital.digital.binary_slicer_fb() 130 | # self.training_correlator = digital.correlate_access_code_bb("1100110011001100", 0) 131 | # self.cma = digital.cma_equalizer_cc 132 | #just a note here: a complex combined quad demod/slicer could be based on if's rather than an actual quad demod, right? 133 | #in fact all the constellation decoders up to QPSK could operate on complex data w/o doing the whole atan thing 134 | 135 | self.diff = gr.diff_decoder_bb(2) 136 | self.invert = ais.invert() #NRZI signal diff decoded and inverted should give original signal 137 | 138 | self.connect(self, self.gmsk_sync) 139 | 140 | if(options.viterbi is False): 141 | self.connect(self.gmsk_sync, self.clockrec, self.demod, self.slicer, self.diff, self.invert, self) 142 | #self.connect(self.gmsk_sync, self.demod, self.clockrec, self.tcslicer, self.training_correlator) 143 | #self.connect(self.clockrec, self.delay, (self.dfe, 0)) 144 | #self.connect(self.training_correlator, (self.dfe, 1)) 145 | #self.connect(self.dfe, self.slicer, self.diff, self.invert, self) 146 | 147 | else: 148 | self.connect(self.gmsk_sync, self.costas, self.resample, self.clockrec) 149 | self.connect(self.clockrec, (self.fomult, 0)) 150 | self.connect(self.fo, (self.fomult, 1)) 151 | self.connect(self.fomult, self.mf0) 152 | self.connect(self.fomult, self.mf1) 153 | self.connect(self.mf0, (self.streams2stream, 0)) 154 | self.connect(self.mf1, (self.streams2stream, 1)) 155 | self.connect(self.streams2stream, self.trellis, self.diff, self.invert, self) 156 | -------------------------------------------------------------------------------- /python/fsm_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2004 Free Software Foundation, Inc. 4 | # 5 | # This file is part of GNU Radio 6 | # 7 | # GNU Radio is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 3, or (at your option) 10 | # any later version. 11 | # 12 | # GNU Radio is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with GNU Radio; see the file COPYING. If not, write to 19 | # the Free Software Foundation, Inc., 51 Franklin Street, 20 | # Boston, MA 02110-1301, USA. 21 | # 22 | 23 | 24 | import re 25 | import math 26 | import sys 27 | import operator 28 | import numpy 29 | import scipy.linalg 30 | 31 | from gnuradio import trellis 32 | 33 | 34 | 35 | ###################################################################### 36 | # Decimal to any base conversion. 37 | # Convert 'num' to a list of 'l' numbers representing 'num' 38 | # to base 'base' (most significant symbol first). 39 | ###################################################################### 40 | def dec2base(num,base,l): 41 | s=range(l) 42 | n=num 43 | for i in range(l): 44 | s[l-i-1]=n%base 45 | n=int(n/base) 46 | if n!=0: 47 | print 'Number ', num, ' requires more than ', l, 'digits.' 48 | return s 49 | 50 | 51 | ###################################################################### 52 | # Conversion from any base to decimal. 53 | # Convert a list 's' of symbols to a decimal number 54 | # (most significant symbol first) 55 | ###################################################################### 56 | def base2dec(s,base): 57 | num=0 58 | for i in range(len(s)): 59 | num=num*base+s[i] 60 | return num 61 | 62 | 63 | 64 | 65 | ###################################################################### 66 | # Automatically generate the lookup table that maps the FSM outputs 67 | # to channel inputs corresponding to a channel 'channel' and a modulation 68 | # 'mod'. Optional normalization of channel to unit energy. 69 | # This table is used by the 'metrics' block to translate 70 | # channel outputs to metrics for use with the Viterbi algorithm. 71 | # Limitations: currently supports only one-dimensional modulations. 72 | ###################################################################### 73 | def make_isi_lookup(mod,channel,normalize): 74 | dim=mod[0] 75 | constellation = mod[1] 76 | 77 | if normalize: 78 | p = 0 79 | for i in range(len(channel)): 80 | p = p + channel[i]**2 81 | for i in range(len(channel)): 82 | channel[i] = channel[i]/math.sqrt(p) 83 | 84 | lookup=range(len(constellation)**len(channel)) 85 | for o in range(len(constellation)**len(channel)): 86 | ss=dec2base(o,len(constellation),len(channel)) 87 | ll=0 88 | for i in range(len(channel)): 89 | ll=ll+constellation[ss[i]]*channel[i] 90 | lookup[o]=ll 91 | return (1,lookup) 92 | 93 | 94 | 95 | 96 | 97 | 98 | ###################################################################### 99 | # Automatically generate the signals appropriate for CPM 100 | # decomposition. 101 | # This decomposition is based on the paper by B. Rimoldi 102 | # "A decomposition approach to CPM", IEEE Trans. Info Theory, March 1988 103 | # See also my own notes at http://www.eecs.umich.edu/~anastas/docs/cpm.pdf 104 | ###################################################################### 105 | def make_cpm_signals(K,P,M,L,q,frac): 106 | 107 | Q=numpy.size(q)/L 108 | h=(1.0*K)/P 109 | f0=-h*(M-1)/2 110 | dt=0.0; # maybe start at t=0.5 111 | t=(dt+numpy.arange(0,Q))/Q 112 | qq=numpy.zeros(Q) 113 | for m in range(L): 114 | qq=qq + q[m*Q:m*Q+Q] 115 | w=math.pi*h*(M-1)*t-2*math.pi*h*(M-1)*qq+math.pi*h*(L-1)*(M-1) 116 | 117 | X=(M**L)*P 118 | PSI=numpy.empty((X,Q)) 119 | for x in range(X): 120 | xv=dec2base(x/P,M,L) 121 | xv=numpy.append(xv, x%P) 122 | qq1=numpy.zeros(Q) 123 | for m in range(L): 124 | qq1=qq1+xv[m]*q[m*Q:m*Q+Q] 125 | psi=2*math.pi*h*xv[-1]+4*math.pi*h*qq1+w 126 | #print psi 127 | PSI[x]=psi 128 | PSI = numpy.transpose(PSI) 129 | SS=numpy.exp(1j*PSI) # contains all signals as columns 130 | #print SS 131 | 132 | 133 | # Now we need to orthogonalize the signals 134 | F = scipy.linalg.orth(SS) # find an orthonormal basis for SS 135 | #print numpy.dot(numpy.transpose(F.conjugate()),F) # check for orthonormality 136 | S = numpy.dot(numpy.transpose(F.conjugate()),SS) 137 | #print F 138 | #print S 139 | 140 | # We only want to keep those dimensions that contain most 141 | # of the energy of the overall constellation (eg, frac=0.9 ==> 90%) 142 | # evaluate mean energy in each dimension 143 | E=numpy.sum(numpy.absolute(S)**2,axis=1)/Q 144 | E=E/numpy.sum(E) 145 | #print E 146 | Es = -numpy.sort(-E) 147 | Esi = numpy.argsort(-E) 148 | #print Es 149 | #print Esi 150 | Ecum=numpy.cumsum(Es) 151 | #print Ecum 152 | v0=numpy.searchsorted(Ecum,frac) 153 | N = v0+1 154 | #print v0 155 | #print Esi[0:v0+1] 156 | Ff=numpy.transpose(numpy.transpose(F)[Esi[0:v0+1]]) 157 | #print Ff 158 | Sf = S[Esi[0:v0+1]] 159 | #print Sf 160 | 161 | 162 | return (f0,SS,S,F,Sf,Ff,N) 163 | #return f0 164 | 165 | 166 | 167 | 168 | ###################################################################### 169 | # A list of common modulations. 170 | # Format: (dimensionality,constellation) 171 | ###################################################################### 172 | pam2 = (1,[-1, 1]) 173 | pam4 = (1,[-3, -1, 3, 1]) # includes Gray mapping 174 | pam8 = (1,[-7, -5, -3, -1, 1, 3, 5, 7]) 175 | 176 | psk4=(2,[1, 0, \ 177 | 0, 1, \ 178 | 0, -1,\ 179 | -1, 0]) # includes Gray mapping 180 | psk8=(2,[math.cos(2*math.pi*0/8), math.sin(2*math.pi*0/8), \ 181 | math.cos(2*math.pi*1/8), math.sin(2*math.pi*1/8), \ 182 | math.cos(2*math.pi*2/8), math.sin(2*math.pi*2/8), \ 183 | math.cos(2*math.pi*3/8), math.sin(2*math.pi*3/8), \ 184 | math.cos(2*math.pi*4/8), math.sin(2*math.pi*4/8), \ 185 | math.cos(2*math.pi*5/8), math.sin(2*math.pi*5/8), \ 186 | math.cos(2*math.pi*6/8), math.sin(2*math.pi*6/8), \ 187 | math.cos(2*math.pi*7/8), math.sin(2*math.pi*7/8)]) 188 | 189 | orth2 = (2,[1, 0, \ 190 | 0, 1]) 191 | orth4=(4,[1, 0, 0, 0, \ 192 | 0, 1, 0, 0, \ 193 | 0, 0, 1, 0, \ 194 | 0, 0, 0, 1]) 195 | 196 | ###################################################################### 197 | # A list of channels to be tested 198 | ###################################################################### 199 | 200 | # C test channel (J. Proakis, Digital Communications, McGraw-Hill Inc., 2001) 201 | c_channel = [0.227, 0.460, 0.688, 0.460, 0.227] 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | if __name__ == '__main__': 213 | f1=trellis.fsm('fsm_files/awgn1o2_4.fsm') 214 | #f2=trellis.fsm('fsm_files/awgn2o3_4.fsm') 215 | #print f1.I(), f1.S(), f1.O() 216 | #print f1.NS() 217 | #print f1.OS() 218 | #print f2.I(), f2.S(), f2.O() 219 | #print f2.NS() 220 | #print f2.OS() 221 | ##f1.write_trellis_svg('f1.svg',4) 222 | #f2.write_trellis_svg('f2.svg',4) 223 | #f=fsm_concatenate(f1,f2) 224 | #f=fsm_radix(f1,2) 225 | 226 | #print "----------\n" 227 | #print f.I(), f.S(), f.O() 228 | #print f.NS() 229 | #print f.OS() 230 | #f.write_trellis_svg('f.svg',4) 231 | 232 | q=numpy.arange(0,8)/(2.0*8) 233 | (f0,SS,S,F,Sf,Ff,N) = make_cpm_signals(1,2,2,1,q,0.99) 234 | 235 | -------------------------------------------------------------------------------- /python/gmsk_sync.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from gnuradio import gr 4 | from gnuradio import eng_notation 5 | from gnuradio import window 6 | from gnuradio import digital 7 | import gr_ais_swig as ais 8 | from math import pi 9 | 10 | class square_and_fft_sync(gr.hier_block2): 11 | def __init__(self, samplerate, bits_per_sec, fftlen): 12 | gr.hier_block2.__init__(self, "gmsk_sync", 13 | gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature 14 | gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature 15 | 16 | #this is just the old square-and-fft method 17 | #ais.freqest is simply looking for peaks spaced bits-per-sec apart 18 | self.square = gr.multiply_cc(1) 19 | self.fftvect = gr.stream_to_vector(gr.sizeof_gr_complex, fftlen) 20 | self.fft = gr.fft_vcc(fftlen, True, window.rectangular(fftlen), True) 21 | self.freqest = ais.freqest(int(samplerate), int(bits_per_sec), fftlen) 22 | self.repeat = gr.repeat(gr.sizeof_float, fftlen) 23 | self.fm = gr.frequency_modulator_fc(-1.0/(float(samplerate)/(2*pi))) 24 | self.mix = gr.multiply_cc(1) 25 | 26 | self.connect(self, (self.square, 0)) 27 | self.connect(self, (self.square, 1)) 28 | #this is the feedforward branch 29 | self.connect(self, (self.mix, 0)) 30 | #this is the feedback branch 31 | self.connect(self.square, self.fftvect, self.fft, self.freqest, self.repeat, self.fm, (self.mix, 1)) 32 | #and this is the output 33 | self.connect(self.mix, self) 34 | -------------------------------------------------------------------------------- /swig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Include swig generation macros 22 | ######################################################################## 23 | find_package(SWIG) 24 | find_package(PythonLibs) 25 | if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND) 26 | return() 27 | endif() 28 | include(GrSwig) 29 | include(GrPython) 30 | 31 | ######################################################################## 32 | # Setup swig generation 33 | ######################################################################## 34 | foreach(incdir ${GNURADIO_CORE_INCLUDE_DIRS}) 35 | list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/swig) 36 | endforeach(incdir) 37 | 38 | foreach(incdir ${GRUEL_INCLUDE_DIRS}) 39 | list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/gruel/swig) 40 | endforeach(incdir) 41 | 42 | set(GR_SWIG_LIBRARIES gnuradio-gr_ais) 43 | set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr_ais_swig_doc.i) 44 | set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include) 45 | 46 | GR_SWIG_MAKE(gr_ais_swig gr_ais_swig.i) 47 | 48 | ######################################################################## 49 | # Install the build swig module 50 | ######################################################################## 51 | GR_SWIG_INSTALL(TARGETS gr_ais_swig DESTINATION ${GR_PYTHON_DIR}/gr_ais) 52 | 53 | ######################################################################## 54 | # Install swig .i files for development 55 | ######################################################################## 56 | install( 57 | FILES 58 | gr_ais_swig.i 59 | ${CMAKE_CURRENT_BINARY_DIR}/gr_ais_swig_doc.i 60 | DESTINATION $(GR_INCLUDE_DIR)/gr_ais/swig 61 | ) 62 | -------------------------------------------------------------------------------- /swig/gr_ais_swig.i: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | 3 | #define GR_AIS_API 4 | 5 | %include "gnuradio.i" // the common stuff 6 | 7 | %{ 8 | #include "ais_invert.h" 9 | #include "ais_unstuff.h" 10 | #include "ais_parse.h" 11 | #include "ais_extended_lms_dfe_ff.h" 12 | #include "ais_freqest.h" 13 | %} 14 | 15 | //load generated python docstrings 16 | %include "gr_ais_swig_doc.i" 17 | 18 | GR_SWIG_BLOCK_MAGIC(ais,invert); 19 | 20 | ais_invert_sptr ais_make_invert(); 21 | 22 | class ais_invert : public gr_sync_block 23 | { 24 | private: 25 | ais_invert(); 26 | 27 | public: 28 | }; 29 | 30 | GR_SWIG_BLOCK_MAGIC(ais,unstuff); 31 | 32 | ais_unstuff_sptr ais_make_unstuff(); 33 | 34 | class ais_unstuff : public gr_block 35 | { 36 | private: 37 | ais_unstuff(); 38 | 39 | public: 40 | }; 41 | 42 | GR_SWIG_BLOCK_MAGIC(ais,parse); 43 | 44 | ais_parse_sptr ais_make_parse(gr_msg_queue_sptr queue, char designator); 45 | 46 | class ais_parse : public gr_sync_block 47 | { 48 | private: 49 | ais_parse(gr_msg_queue_sptr queue, char designator); 50 | 51 | public: 52 | }; 53 | 54 | GR_SWIG_BLOCK_MAGIC(ais,extended_lms_dfe_ff); 55 | 56 | ais_extended_lms_dfe_ff_sptr ais_make_extended_lms_dfe_ff(float lambda_ff, float lambda_fb , 57 | unsigned int num_fftaps, unsigned int num_fbtaps); 58 | 59 | class ais_extended_lms_dfe_ff : public gr_sync_block 60 | { 61 | private: 62 | ais_extended_lms_dfe_ff(float lambda_ff, float lambda_fb , 63 | unsigned int num_fftaps, unsigned int num_fbtaps); 64 | 65 | public: 66 | }; 67 | 68 | GR_SWIG_BLOCK_MAGIC(ais,freqest); 69 | 70 | ais_freqest_sptr ais_make_freqest(int sample_rate, int data_rate, int fftlen); 71 | 72 | class ais_freqest : public gr_sync_block 73 | { 74 | private: 75 | ais_freqest(int sample_rate, int data_rate, int fftlen); 76 | 77 | public: 78 | }; 79 | --------------------------------------------------------------------------------