mirror of
				https://github.com/brmlab/osmo-tetra.git
				synced 2025-10-31 15:33:59 +01:00 
			
		
		
		
	initial import of TETRA demodulator based on gnuradio blocks
This commit is contained in:
		
						commit
						a4c4e5a1ab
					
				
					 16 changed files with 1111 additions and 0 deletions
				
			
		
							
								
								
									
										27
									
								
								src/demod/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/demod/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| COPYING | ||||
| INSTALL | ||||
| Makefile | ||||
| Makefile.in | ||||
| aclocal.m4 | ||||
| config.guess | ||||
| config.h | ||||
| config.h.in | ||||
| config.h.in~ | ||||
| config.log | ||||
| config.status | ||||
| config.sub | ||||
| config/libtool.m4 | ||||
| config/ltoptions.m4 | ||||
| config/ltsugar.m4 | ||||
| config/ltversion.m4 | ||||
| config/lt~obsolete.m4 | ||||
| configure | ||||
| install-sh | ||||
| libtool | ||||
| ltmain.sh | ||||
| missing | ||||
| py-compile | ||||
| py_run_tests | ||||
| stamp-h1 | ||||
| autom4te.cache | ||||
| *.sw? | ||||
							
								
								
									
										39
									
								
								src/demod/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/demod/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| # | ||||
| # Copyright 2001,2006,2008,2009 Free Software Foundation, Inc. | ||||
| #  | ||||
| # This file is part of GNU Radio | ||||
| #  | ||||
| # GNU Radio is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3, or (at your option) | ||||
| # any later version. | ||||
| #  | ||||
| # GNU Radio is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with GNU Radio; see the file COPYING.  If not, write to | ||||
| # the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| # Boston, MA 02110-1301, USA. | ||||
| #  | ||||
| 
 | ||||
| ACLOCAL_AMFLAGS = -I config | ||||
| AUTOMAKE_OPTIONS = foreign | ||||
| 
 | ||||
| include $(top_srcdir)/Makefile.common | ||||
| 
 | ||||
| 
 | ||||
| SUBDIRS = python apps config grc | ||||
| 
 | ||||
| export pythondir | ||||
| 
 | ||||
| install-data-hook: | ||||
| 	@if ! python -c "import gnuradio" > /dev/null 2>&1; then\ | ||||
| 		printf "\n*** Post-Install Message ***\ | ||||
| 		\nWarning: python could not find the gnuradio module.\ | ||||
| 		\nMake sure that $${pythondir} is in your PYTHONPATH\n\n";\ | ||||
| 	fi | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										77
									
								
								src/demod/Makefile.common
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/demod/Makefile.common
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| # -*- Makefile -*- | ||||
| # | ||||
| # Copyright 2004,2006,2009,2010 Free Software Foundation, Inc. | ||||
| #  | ||||
| # This file is part of GNU Radio | ||||
| #  | ||||
| # GNU Radio is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3, or (at your option) | ||||
| # any later version. | ||||
| #  | ||||
| # GNU Radio is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with GNU Radio; see the file COPYING.  If not, write to | ||||
| # the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| # Boston, MA 02110-1301, USA. | ||||
| #  | ||||
| 
 | ||||
| # The name of this "out-of-tree" module | ||||
| modname = tetra_demod | ||||
| 
 | ||||
| # these flags are used when compiling non-SWIG-wrapper files | ||||
| # when going in to non-SWIG libraries | ||||
| AM_CXXFLAGS = @autoconf_default_CXXFLAGS@ | ||||
| 
 | ||||
| # Sets ABI version in SONAME and appends -LIBVER to filename | ||||
| LTVERSIONFLAGS = -version-info 0:0:0 -release $(LIBVER) | ||||
| 
 | ||||
| # these flags are used when compiling any CXX file | ||||
| AM_CPPFLAGS = \ | ||||
| 	$(STD_DEFINES_AND_INCLUDES) \ | ||||
| 	$(PYTHON_CPPFLAGS) \ | ||||
| 	$(CPPUNIT_INCLUDES) \ | ||||
| 	$(GNURADIO_CORE_CPPFLAGS) | ||||
| 
 | ||||
| # these are used by both SWIG and CXX | ||||
| STD_DEFINES_AND_INCLUDES = \ | ||||
| 	$(DEFINES) \ | ||||
| 	-I$(abs_top_srcdir)/lib \ | ||||
| 	-I$(GNURADIO_CORE_INCLUDEDIR) \ | ||||
| 	-I$(GNURADIO_CORE_INCLUDEDIR)/swig | ||||
| 
 | ||||
| # includes | ||||
| modincludedir = $(includedir)/$(modname) | ||||
| 
 | ||||
| # swig includes  | ||||
| swigincludedir = $(modincludedir)/swig | ||||
| 
 | ||||
| # Install this stuff in the appropriate subdirectory | ||||
| # This usually ends up at: | ||||
| #   ${prefix}/lib/python${python_version}/site-packages/$(modname) | ||||
| 
 | ||||
| modpythondir = $(pythondir)/$(modname) | ||||
| modpyexecdir = $(pyexecdir)/$(modname) | ||||
| 
 | ||||
| # Data directory for grc block wrappers | ||||
| grc_blocksdir = $(prefix)/share/gnuradio/grc/blocks | ||||
| 
 | ||||
| # Don't assume that make predefines $(RM), because BSD make does | ||||
| # not. We define it now in configure.ac using AM_PATH_PROG, but now | ||||
| # here have to add a -f to be like GNU make. | ||||
| RM=$(RM_PROG) -f | ||||
| 
 | ||||
| # Other common defines; use "+=" to add to these | ||||
| STAMPS = | ||||
| MOSTLYCLEANFILES = $(BUILT_SOURCES) $(STAMPS) *.pyc *.pyo *~ *.tmp *.loT | ||||
| 
 | ||||
| # Don't distribute the files defined in the variable 'no_dist_files' | ||||
| dist-hook: | ||||
| 	@for file in $(no_dist_files); do \ | ||||
| 		echo $(RM) $(distdir)/$$file; \ | ||||
| 		$(RM) $(distdir)/$$file; \ | ||||
| 	done; | ||||
							
								
								
									
										0
									
								
								src/demod/apps/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/demod/apps/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										31
									
								
								src/demod/config/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/demod/config/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| # | ||||
| # Copyright 2001,2006,2008,2009,2010 Free Software Foundation, Inc. | ||||
| #  | ||||
| # This file is part of GNU Radio | ||||
| #  | ||||
| # GNU Radio is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3, or (at your option) | ||||
| # any later version. | ||||
| #  | ||||
| # GNU Radio is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with GNU Radio; see the file COPYING.  If not, write to | ||||
| # the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| # Boston, MA 02110-1301, USA. | ||||
| #  | ||||
| 
 | ||||
| include $(top_srcdir)/Makefile.common | ||||
| 
 | ||||
| # Install m4 macros in this directory | ||||
| m4datadir = $(datadir)/aclocal | ||||
| 
 | ||||
| # List your m4 macros here | ||||
| m4macros = \ | ||||
| 	gr_standalone.m4 | ||||
| 
 | ||||
| EXTRA_DIST = $(m4macros)  | ||||
							
								
								
									
										135
									
								
								src/demod/config/gr_standalone.m4
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/demod/config/gr_standalone.m4
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | |||
| dnl | ||||
| dnl Copyright 2008,2009 Free Software Foundation, Inc. | ||||
| dnl  | ||||
| dnl This file is part of GNU Radio | ||||
| dnl  | ||||
| dnl GNU Radio is free software; you can redistribute it and/or modify | ||||
| dnl it under the terms of the GNU General Public License as published by | ||||
| dnl the Free Software Foundation; either version 3, or (at your option) | ||||
| dnl any later version. | ||||
| dnl  | ||||
| dnl GNU Radio is distributed in the hope that it will be useful, | ||||
| dnl but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| dnl GNU General Public License for more details. | ||||
| dnl  | ||||
| dnl You should have received a copy of the GNU General Public License along | ||||
| dnl with this program; if not, write to the Free Software Foundation, Inc., | ||||
| dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
| dnl | ||||
| 
 | ||||
| dnl | ||||
| dnl GR_STANDALONE([package],[version]) | ||||
| dnl | ||||
| dnl Handles the bulk of the configure.ac work for an out-of-tree build | ||||
| dnl | ||||
| dnl N.B., this is an m4_define because if it were an AC_DEFUN it would | ||||
| dnl get called too late to be useful. | ||||
| 
 | ||||
| m4_define([GR_STANDALONE], | ||||
| [ | ||||
|   AC_CONFIG_SRCDIR([config/gr_standalone.m4]) | ||||
|   AM_CONFIG_HEADER(config.h) | ||||
| 
 | ||||
|   dnl Remember if the user explicity set CXXFLAGS | ||||
|   if test -n "${CXXFLAGS}"; then | ||||
|     user_set_cxxflags=yes | ||||
|   fi | ||||
| 
 | ||||
|   LF_CONFIGURE_CC | ||||
|   LF_CONFIGURE_CXX | ||||
|   GR_LIB64		dnl check for lib64 suffix after choosing compilers | ||||
| 
 | ||||
|   dnl The three macros above are known to override CXXFLAGS if the user | ||||
|   dnl didn't specify them.  Though I'm sure somebody thought this was | ||||
|   dnl a good idea, it makes it hard to use other than -g -O2 when compiling | ||||
|   dnl selected files.  Thus we "undo" the damage here... | ||||
|   dnl  | ||||
|   dnl If the user specified CXXFLAGS, we use them.  Otherwise when compiling | ||||
|   dnl the output of swig use use -O1 if we're using g++. | ||||
|   dnl See Makefile.common for the rest of the magic. | ||||
|   if test "$user_set_cxxflags" != yes; then | ||||
|     autoconf_default_CXXFLAGS="$CXXFLAGS" | ||||
|     if test "$GXX" = yes; then | ||||
|       case "$host_cpu" in | ||||
|     	powerpc*) | ||||
| 	   dnl "-O1" is broken on the PPC for some reason | ||||
| 	   dnl (at least as of g++ 4.1.1) | ||||
| 	   swig_CXXFLAGS="-g1 -O2 -Wno-strict-aliasing -Wno-parentheses" | ||||
| 	;; | ||||
|     	*)  | ||||
| 	swig_CXXFLAGS="-g -O1 -Wno-strict-aliasing -Wno-parentheses" | ||||
| 	;; | ||||
|       esac | ||||
|     fi | ||||
|   fi | ||||
|   AC_SUBST(autoconf_default_CXXFLAGS) | ||||
|   AC_SUBST(swig_CXXFLAGS) | ||||
| 
 | ||||
|   dnl add ${prefix}/lib${gr_libdir_suffix}/pkgconfig to the head of the PKG_CONFIG_PATH | ||||
|   if test x${PKG_CONFIG_PATH} = x; then | ||||
|       PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig | ||||
|   else | ||||
|       PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig:${PKG_CONFIG_PATH} | ||||
|   fi | ||||
|   export PKG_CONFIG_PATH | ||||
| 
 | ||||
|   LF_SET_WARNINGS | ||||
|   GR_SET_GPROF | ||||
|   GR_SET_PROF | ||||
|   AM_PROG_AS | ||||
|   AC_PROG_LN_S | ||||
|   AC_PROG_MAKE_SET | ||||
|   AC_PROG_INSTALL | ||||
|   AC_PATH_PROG([RM_PROG], [rm]) | ||||
| 
 | ||||
|   AC_LIBTOOL_WIN32_DLL | ||||
|   AC_ENABLE_SHARED	dnl do build shared libraries | ||||
|   AC_DISABLE_STATIC	dnl don't build static libraries | ||||
|   m4_ifdef([LT_INIT],[LT_INIT],[AC_PROG_LIBTOOL]) | ||||
|   dnl GR_FORTRAN | ||||
| 
 | ||||
|   GR_NO_UNDEFINED	dnl do we need the -no-undefined linker flag | ||||
|   GR_SCRIPTING		dnl Locate python, SWIG, etc | ||||
| 
 | ||||
|   dnl Checks for header files. | ||||
|   AC_HEADER_STDC | ||||
| 
 | ||||
|   dnl Checks for typedefs, structures, and compiler characteristics. | ||||
|   AC_C_CONST | ||||
|   AC_C_INLINE | ||||
|   AC_TYPE_SIZE_T | ||||
|   AC_HEADER_TIME | ||||
|   AC_C_BIGENDIAN | ||||
| 
 | ||||
|   dnl Check for Mingw support | ||||
|   GR_PWIN32 | ||||
| 
 | ||||
|   AC_CHECK_PROG([XMLTO],[xmlto],[yes],[]) | ||||
|   AM_CONDITIONAL([HAS_XMLTO], [test x$XMLTO = xyes]) | ||||
| 
 | ||||
|   PKG_CHECK_MODULES(GNURADIO_CORE, gnuradio-core >= 3) | ||||
|   LIBS="$LIBS $GNURADIO_CORE_LIBS" | ||||
| 
 | ||||
|   dnl Allow user to choose whether to generate SWIG/Python  | ||||
|   dnl Default is enabled | ||||
|   AC_ARG_ENABLE([python], | ||||
|     [AS_HELP_STRING([--enable-python], | ||||
|       [generate SWIG/Python components (default is yes)])], | ||||
|     [case "${enableval}" in | ||||
|        yes) enable_python=yes ;; | ||||
|        no) enable_python=no ;; | ||||
|        *) AC_MSG_ERROR([bad value ${enableval} for --enable-python]) ;; | ||||
|      esac], | ||||
|     [enable_python=yes]   | ||||
|   ) | ||||
|   AM_CONDITIONAL([PYTHON], [test x$enable_python = xyes]) | ||||
| 
 | ||||
|   dnl Define where to look for cppunit includes and libs | ||||
|   dnl sets CPPUNIT_CFLAGS and CPPUNIT_LIBS | ||||
|   dnl Try using pkg-config first, then fall back to cppunit-config. | ||||
|   PKG_CHECK_EXISTS(cppunit, | ||||
|     [PKG_CHECK_MODULES(CPPUNIT, cppunit >= 1.9.14)], | ||||
|     [AM_PATH_CPPUNIT([1.9.14],[], | ||||
| 		     [AC_MSG_ERROR([GNU Radio requires cppunit.  Stop])])]) | ||||
| ]) | ||||
							
								
								
									
										55
									
								
								src/demod/configure.ac
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/demod/configure.ac
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| dnl  | ||||
| dnl  Copyright 2004,2005,2007,2008,2009 Free Software Foundation, Inc. | ||||
| dnl   | ||||
| dnl  This file is part of GNU Radio | ||||
| dnl   | ||||
| dnl  GNU Radio is free software; you can redistribute it and/or modify | ||||
| dnl  it under the terms of the GNU General Public License as published by | ||||
| dnl  the Free Software Foundation; either version 3, or (at your option) | ||||
| dnl  any later version. | ||||
| dnl   | ||||
| dnl  GNU Radio is distributed in the hope that it will be useful, | ||||
| dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| dnl  GNU General Public License for more details. | ||||
| dnl   | ||||
| dnl  You should have received a copy of the GNU General Public License | ||||
| dnl  along with GNU Radio; see the file COPYING.  If not, write to | ||||
| dnl  the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| dnl  Boston, MA 02110-1301, USA. | ||||
| dnl  | ||||
| 
 | ||||
| 
 | ||||
| AC_INIT([tetra-demod], [0.0.1]) | ||||
| AC_PREREQ(2.57) | ||||
| AC_CONFIG_AUX_DIR([.])	 | ||||
| 
 | ||||
| AC_CANONICAL_BUILD | ||||
| AC_CANONICAL_HOST | ||||
| AC_CANONICAL_TARGET | ||||
| 
 | ||||
| GR_VERSION | ||||
| dnl ustar required to have pathnames > 99 chars | ||||
| _AM_SET_OPTION([tar-ustar]) | ||||
| AM_INIT_AUTOMAKE([]) | ||||
| 
 | ||||
| dnl This is kind of non-standard, but it sure shortens up this file :-) | ||||
| m4_include([config/gr_standalone.m4]) | ||||
| GR_STANDALONE | ||||
| AM_PATH_PYTHON | ||||
| 
 | ||||
| 
 | ||||
| AC_CONFIG_FILES([\ | ||||
| 	  Makefile \ | ||||
| 	  apps/Makefile \ | ||||
| 	  config/Makefile \ | ||||
| 	  grc/Makefile \ | ||||
| 	  python/Makefile \ | ||||
| 	  python/py_run_tests \ | ||||
| 	]) | ||||
| 
 | ||||
| dnl run_tests is created from run_tests.in.  Make it executable. | ||||
| AC_CONFIG_COMMANDS([run_tests], [chmod +x python/py_run_tests]) | ||||
| 
 | ||||
| AC_OUTPUT | ||||
| 
 | ||||
							
								
								
									
										22
									
								
								src/demod/grc/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/demod/grc/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| # (C) 2011 by Holger Hans Peter Freyther | ||||
| # All Rights Reserved | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU Affero General Public License as published by | ||||
| # the Free Software Foundation; either version 3 of the License, or | ||||
| # (at your option) any later version. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU Affero General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU Affero General Public License | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| 
 | ||||
| include $(top_srcdir)/Makefile.common | ||||
| 
 | ||||
| grcblocksdir = $(grc_blocksdir) | ||||
| dist_grcblocks_DATA = \ | ||||
| 	tetra_demod_qpsk.xml | ||||
							
								
								
									
										18
									
								
								src/demod/grc/tetra_demod_qpsk.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/demod/grc/tetra_demod_qpsk.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| <?xml version="1.0"?> | ||||
| <block> | ||||
|     <name>Tetra QPSK pi/4 demodulation</name> | ||||
|     <key>tetra_demod</key> | ||||
|     <category>Tetra</category> | ||||
|     <import>import tetra_demod</import> | ||||
|     <make>tetra_demod.demod()</make> | ||||
| 
 | ||||
|     <sink> | ||||
|         <name>in</name> | ||||
|         <type>complex</type> | ||||
|     </sink> | ||||
| 
 | ||||
|     <source> | ||||
|         <name>out</name> | ||||
|         <type>float</type> | ||||
|     </source> | ||||
| </block> | ||||
							
								
								
									
										37
									
								
								src/demod/python/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/demod/python/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| # | ||||
| # Copyright 2001,2006,2008,2009 Free Software Foundation, Inc. | ||||
| #  | ||||
| # This file is part of GNU Radio | ||||
| #  | ||||
| # GNU Radio is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3, or (at your option) | ||||
| # any later version. | ||||
| #  | ||||
| # GNU Radio is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with GNU Radio; see the file COPYING.  If not, write to | ||||
| # the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| # Boston, MA 02110-1301, USA. | ||||
| #  | ||||
| # | ||||
| include $(top_srcdir)/Makefile.common | ||||
| 
 | ||||
| bin_SCRIPTS = \ | ||||
| 	tetra-demod.py \ | ||||
| 	usrp1-tetra_demod.py \ | ||||
| 	usrp2-tetra_demod.py | ||||
| 
 | ||||
| EXTRA_DIST = py_run_tests.in tetra-demod.py usrp1-tetra_demod.py usrp2-tetra_demod.py | ||||
| TESTS = py_run_tests | ||||
| 
 | ||||
| modpython_PYTHON = \ | ||||
| 	__init__.py \ | ||||
| 	cqpsk.py | ||||
| 
 | ||||
| noinst_PYTHON = \ | ||||
| 	qa_tetra.py | ||||
							
								
								
									
										28
									
								
								src/demod/python/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/demod/python/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| """ | ||||
|  (C) 2011 by Holger Hans Peter Freyther | ||||
|  All Rights Reserved | ||||
| 
 | ||||
|  This program is free software; you can redistribute it and/or modify | ||||
|  it under the terms of the GNU Affero General Public License as published by | ||||
|  the Free Software Foundation; either version 3 of the License, or | ||||
|  (at your option) any later version. | ||||
| 
 | ||||
|  This program is distributed in the hope that it will be useful, | ||||
|  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  GNU Affero General Public License for more details. | ||||
| 
 | ||||
|  You should have received a copy of the GNU Affero General Public License | ||||
|  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| """ | ||||
| 
 | ||||
| import cqpsk | ||||
| 
 | ||||
| def demod(): | ||||
|     return cqpsk.cqpsk_demod(samples_per_symbol = 2, | ||||
|                              excess_bw=0.35, | ||||
|                              costas_alpha=0.03, | ||||
|                              gain_mu=0.05, | ||||
|                              mu=0.05, | ||||
|                              omega_relative_limit=0.05) | ||||
| 
 | ||||
							
								
								
									
										350
									
								
								src/demod/python/cqpsk.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								src/demod/python/cqpsk.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,350 @@ | |||
| # | ||||
| # Copyright 2005,2006,2007 Free Software Foundation, Inc. | ||||
| # | ||||
| # cqpsk.py (C) Copyright 2009, KA1RBI | ||||
| #  | ||||
| # This file is part of GNU Radio | ||||
| #  | ||||
| # GNU Radio is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3, or (at your option) | ||||
| # any later version. | ||||
| #  | ||||
| # GNU Radio is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with GNU Radio; see the file COPYING.  If not, write to | ||||
| # the Free Software Foundation, Inc., 51 Franklin Street, | ||||
| # Boston, MA 02110-1301, USA. | ||||
| #  | ||||
| 
 | ||||
| # See gnuradio-examples/python/digital for examples | ||||
| 
 | ||||
| """ | ||||
| differential PI/4 CQPSK modulation and demodulation. | ||||
| """ | ||||
| 
 | ||||
| from gnuradio import gr, gru, modulation_utils | ||||
| from math import pi, sqrt | ||||
| #import psk | ||||
| import cmath | ||||
| from pprint import pprint | ||||
| 
 | ||||
| # default values (used in __init__ and add_options) | ||||
| _def_samples_per_symbol = 10 | ||||
| _def_excess_bw = 0.35 | ||||
| _def_gray_code = True | ||||
| _def_verbose = False | ||||
| _def_log = False | ||||
| 
 | ||||
| _def_costas_alpha = 0.15 | ||||
| _def_gain_mu = None | ||||
| _def_mu = 0.5 | ||||
| _def_omega_relative_limit = 0.005 | ||||
| 
 | ||||
| 
 | ||||
| # ///////////////////////////////////////////////////////////////////////////// | ||||
| #                           CQPSK modulator | ||||
| # ///////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
| class cqpsk_mod(gr.hier_block2): | ||||
| 
 | ||||
|     def __init__(self, | ||||
|                  samples_per_symbol=_def_samples_per_symbol, | ||||
|                  excess_bw=_def_excess_bw, | ||||
|                  verbose=_def_verbose, | ||||
|                  log=_def_log): | ||||
|         """ | ||||
| 	Hierarchical block for RRC-filtered QPSK modulation. | ||||
| 
 | ||||
| 	The input is a byte stream (unsigned char) and the | ||||
| 	output is the complex modulated signal at baseband. | ||||
| 
 | ||||
| 	@param samples_per_symbol: samples per symbol >= 2 | ||||
| 	@type samples_per_symbol: integer | ||||
| 	@param excess_bw: Root-raised cosine filter excess bandwidth | ||||
| 	@type excess_bw: float | ||||
|         @param verbose: Print information about modulator? | ||||
|         @type verbose: bool | ||||
|         @param debug: Print modualtion data to files? | ||||
|         @type debug: bool | ||||
| 	""" | ||||
| 
 | ||||
| 	gr.hier_block2.__init__(self, "cqpsk_mod", | ||||
| 				gr.io_signature(1, 1, gr.sizeof_char),       # Input signature | ||||
| 				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature | ||||
| 
 | ||||
|         self._samples_per_symbol = samples_per_symbol | ||||
|         self._excess_bw = excess_bw | ||||
| 
 | ||||
|         if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: | ||||
|             raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) | ||||
| 
 | ||||
| 	ntaps = 11 * samples_per_symbol | ||||
|   | ||||
|         arity = 8 | ||||
| 
 | ||||
|         # turn bytes into k-bit vectors | ||||
|         self.bytes2chunks = \ | ||||
|           gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) | ||||
| 
 | ||||
|         #	0	+45	1	[+1] | ||||
|         #	1	+135	3	[+3] | ||||
|         #	2	-45	7	[-1] | ||||
|         #	3	-135	5	[-3] | ||||
|         self.pi4map = [1, 3, 7, 5] | ||||
|         self.symbol_mapper = gr.map_bb(self.pi4map) | ||||
|         self.diffenc = gr.diff_encoder_bb(arity) | ||||
|         self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity]) | ||||
| 
 | ||||
|         # pulse shaping filter | ||||
| 	self.rrc_taps = gr.firdes.root_raised_cosine( | ||||
| 	    self._samples_per_symbol, # gain  (sps since we're interpolating by sps) | ||||
|             self._samples_per_symbol, # sampling rate | ||||
|             1.0,		      # symbol rate | ||||
|             self._excess_bw,          # excess bandwidth (roll-off factor) | ||||
|             ntaps) | ||||
| 
 | ||||
| 	self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) | ||||
| 
 | ||||
|         if verbose: | ||||
|             self._print_verbage() | ||||
|          | ||||
|         if log: | ||||
|             self._setup_logging() | ||||
|              | ||||
| 	# Connect & Initialize base class | ||||
|         self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, | ||||
|                      self.chunks2symbols, self.rrc_filter, self) | ||||
| 
 | ||||
|     def samples_per_symbol(self): | ||||
|         return self._samples_per_symbol | ||||
| 
 | ||||
|     def bits_per_symbol(self=None):   # staticmethod that's also callable on an instance | ||||
|         return 2 | ||||
|     bits_per_symbol = staticmethod(bits_per_symbol)      # make it a static method.  RTFM | ||||
| 
 | ||||
|     def _print_verbage(self): | ||||
|         print "\nModulator:" | ||||
|         print "bits per symbol:     %d" % self.bits_per_symbol() | ||||
|         print "Gray code:           %s" % self._gray_code | ||||
|         print "RRS roll-off factor: %f" % self._excess_bw | ||||
| 
 | ||||
|     def _setup_logging(self): | ||||
|         print "Modulation logging turned on." | ||||
|         self.connect(self.bytes2chunks, | ||||
|                      gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) | ||||
|         self.connect(self.symbol_mapper, | ||||
|                      gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) | ||||
|         self.connect(self.diffenc, | ||||
|                      gr.file_sink(gr.sizeof_char, "tx_diffenc.dat"))         | ||||
|         self.connect(self.chunks2symbols, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) | ||||
|         self.connect(self.rrc_filter, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) | ||||
| 
 | ||||
|     def add_options(parser): | ||||
|         """ | ||||
|         Adds QPSK modulation-specific options to the standard parser | ||||
|         """ | ||||
|         parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, | ||||
|                           help="set RRC excess bandwith factor [default=%default] (PSK)") | ||||
|         parser.add_option("", "--no-gray-code", dest="gray_code", | ||||
|                           action="store_false", default=_def_gray_code, | ||||
|                           help="disable gray coding on modulated bits (PSK)") | ||||
|     add_options=staticmethod(add_options) | ||||
| 
 | ||||
| 
 | ||||
|     def extract_kwargs_from_options(options): | ||||
|         """ | ||||
|         Given command line options, create dictionary suitable for passing to __init__ | ||||
|         """ | ||||
|         return modulation_utils.extract_kwargs_from_options(dqpsk_mod.__init__, | ||||
|                                                             ('self',), options) | ||||
|     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) | ||||
| 
 | ||||
| 
 | ||||
| # ///////////////////////////////////////////////////////////////////////////// | ||||
| #                           CQPSK demodulator | ||||
| # | ||||
| # ///////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
| class cqpsk_demod(gr.hier_block2): | ||||
| 
 | ||||
|     def __init__(self,  | ||||
|                  samples_per_symbol=_def_samples_per_symbol, | ||||
|                  excess_bw=_def_excess_bw, | ||||
|                  costas_alpha=_def_costas_alpha, | ||||
|                  gain_mu=_def_gain_mu, | ||||
|                  mu=_def_mu, | ||||
|                  omega_relative_limit=_def_omega_relative_limit, | ||||
|                  gray_code=_def_gray_code, | ||||
|                  verbose=_def_verbose, | ||||
|                  log=_def_log): | ||||
|         """ | ||||
| 	Hierarchical block for RRC-filtered CQPSK demodulation | ||||
| 
 | ||||
| 	The input is the complex modulated signal at baseband. | ||||
| 	The output is a stream of floats in [ -3 / -1 / +1 / +3 ] | ||||
| 
 | ||||
| 	@param samples_per_symbol: samples per symbol >= 2 | ||||
| 	@type samples_per_symbol: float | ||||
| 	@param excess_bw: Root-raised cosine filter excess bandwidth | ||||
| 	@type excess_bw: float | ||||
|         @param costas_alpha: loop filter gain | ||||
|         @type costas_alphas: float | ||||
|         @param gain_mu: for M&M block | ||||
|         @type gain_mu: float | ||||
|         @param mu: for M&M block | ||||
|         @type mu: float | ||||
|         @param omega_relative_limit: for M&M block | ||||
|         @type omega_relative_limit: float | ||||
|         @param gray_code: Tell modulator to Gray code the bits | ||||
|         @type gray_code: bool | ||||
|         @param verbose: Print information about modulator? | ||||
|         @type verbose: bool | ||||
|         @param debug: Print modualtion data to files? | ||||
|         @type debug: bool | ||||
| 	""" | ||||
| 
 | ||||
| 	gr.hier_block2.__init__(self, "cqpsk_demod", | ||||
| 			        gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature | ||||
| 			        gr.io_signature(1, 1, gr.sizeof_float))       # Output signature | ||||
| 
 | ||||
|         self._samples_per_symbol = samples_per_symbol | ||||
|         self._excess_bw = excess_bw | ||||
|         self._costas_alpha = costas_alpha | ||||
|         self._mm_gain_mu = gain_mu | ||||
|         self._mm_mu = mu | ||||
|         self._mm_omega_relative_limit = omega_relative_limit | ||||
|         self._gray_code = gray_code | ||||
| 
 | ||||
|         if samples_per_symbol < 2: | ||||
|             raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol | ||||
| 
 | ||||
|         arity = pow(2,self.bits_per_symbol()) | ||||
|   | ||||
|         # Automatic gain control | ||||
|         scale = (1.0/16384.0) | ||||
|         self.pre_scaler = gr.multiply_const_cc(scale)   # scale the signal from full-range to +-1 | ||||
|         #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) | ||||
|         self.agc = gr.feedforward_agc_cc(16, 2.0) | ||||
|         | ||||
|         # RRC data filter | ||||
|         ntaps = 11 * samples_per_symbol | ||||
|         self.rrc_taps = gr.firdes.root_raised_cosine( | ||||
|             1.0,                      # gain | ||||
|             self._samples_per_symbol, # sampling rate | ||||
|             1.0,                      # symbol rate | ||||
|             self._excess_bw,          # excess bandwidth (roll-off factor) | ||||
|             ntaps) | ||||
|         self.rrc_filter=gr.interp_fir_filter_ccf(1, self.rrc_taps)         | ||||
| 
 | ||||
|         if not self._mm_gain_mu: | ||||
|             sbs_to_mm = {2: 0.050, 3: 0.075, 4: 0.11, 5: 0.125, 6: 0.15, 7: 0.15} | ||||
|             self._mm_gain_mu = sbs_to_mm[samples_per_symbol] | ||||
| 
 | ||||
|         self._mm_omega = self._samples_per_symbol | ||||
|         self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu | ||||
|         self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha | ||||
|         fmin = -0.025 | ||||
|         fmax = 0.025 | ||||
|          | ||||
|         self.receiver=gr.mpsk_receiver_cc(arity, pi/4.0, | ||||
|                                           self._costas_alpha, self._costas_beta, | ||||
|                                           fmin, fmax, | ||||
|                                           self._mm_mu, self._mm_gain_mu, | ||||
|                                           self._mm_omega, self._mm_gain_omega, | ||||
|                                           self._mm_omega_relative_limit) | ||||
| 
 | ||||
|         # Perform Differential decoding on the constellation | ||||
|         self.diffdec = gr.diff_phasor_cc() | ||||
| 
 | ||||
|         # take angle of the difference (in radians) | ||||
|         self.to_float = gr.complex_to_arg() | ||||
| 
 | ||||
|         # convert from radians such that signal is in -3/-1/+1/+3 | ||||
|         self.rescale = gr.multiply_const_ff( 1 / (pi / 4) ) | ||||
| 
 | ||||
|         if verbose: | ||||
|             self._print_verbage() | ||||
|          | ||||
|         if log: | ||||
|             self._setup_logging() | ||||
|   | ||||
|         # Connect & Initialize base class | ||||
|         self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, | ||||
|                      self.diffdec, self.to_float, self.rescale, self) | ||||
| 
 | ||||
|     def samples_per_symbol(self): | ||||
|         return self._samples_per_symbol | ||||
| 
 | ||||
|     def bits_per_symbol(self=None):   # staticmethod that's also callable on an instance | ||||
|         return 2 | ||||
|     bits_per_symbol = staticmethod(bits_per_symbol)      # make it a static method.  RTFM | ||||
| 
 | ||||
|     def _print_verbage(self): | ||||
|         print "\nDemodulator:" | ||||
|         print "bits per symbol:     %d"   % self.bits_per_symbol() | ||||
|         print "Gray code:           %s"   % self._gray_code | ||||
|         print "RRC roll-off factor: %.2f" % self._excess_bw | ||||
|         print "Costas Loop alpha:   %.2e" % self._costas_alpha | ||||
|         print "Costas Loop beta:    %.2e" % self._costas_beta | ||||
|         print "M&M mu:              %.2f" % self._mm_mu | ||||
|         print "M&M mu gain:         %.2e" % self._mm_gain_mu | ||||
|         print "M&M omega:           %.2f" % self._mm_omega | ||||
|         print "M&M omega gain:      %.2e" % self._mm_gain_omega | ||||
|         print "M&M omega limit:     %.2f" % self._mm_omega_relative_limit | ||||
| 
 | ||||
|     def _setup_logging(self): | ||||
|         print "Modulation logging turned on." | ||||
|         self.connect(self.pre_scaler, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) | ||||
|         self.connect(self.agc, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) | ||||
|         self.connect(self.rrc_filter, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) | ||||
|         self.connect(self.receiver, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) | ||||
|         self.connect(self.diffdec, | ||||
|                      gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))         | ||||
|         self.connect(self.to_float, | ||||
|                      gr.file_sink(gr.sizeof_float, "rx_to_float.dat")) | ||||
|         self.connect(self.rescale, | ||||
|                      gr.file_sink(gr.sizeof_float, "rx_rescale.dat")) | ||||
| 
 | ||||
|     def add_options(parser): | ||||
|         """ | ||||
|         Adds modulation-specific options to the standard parser | ||||
|         """ | ||||
|         parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, | ||||
|                           help="set RRC excess bandwith factor [default=%default] (PSK)") | ||||
|         parser.add_option("", "--no-gray-code", dest="gray_code", | ||||
|                           action="store_false", default=_def_gray_code, | ||||
|                           help="disable gray coding on modulated bits (PSK)") | ||||
|         parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha, | ||||
|                           help="set Costas loop alpha value [default=%default] (PSK)") | ||||
|         parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu, | ||||
|                           help="set M&M symbol sync loop gain mu value [default=%default] (PSK)") | ||||
|         parser.add_option("", "--mu", type="float", default=_def_mu, | ||||
|                           help="set M&M symbol sync loop mu value [default=%default] (PSK)") | ||||
|     add_options=staticmethod(add_options) | ||||
| 
 | ||||
|     def extract_kwargs_from_options(options): | ||||
|         """ | ||||
|         Given command line options, create dictionary suitable for passing to __init__ | ||||
|         """ | ||||
|         return modulation_utils.extract_kwargs_from_options( | ||||
|             cqpsk_demod.__init__, ('self',), options) | ||||
|     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) | ||||
| 
 | ||||
| 
 | ||||
| # | ||||
| # Add these to the mod/demod registry | ||||
| # | ||||
| #modulation_utils.add_type_1_mod('cqpsk', cqpsk_mod) | ||||
| #modulation_utils.add_type_1_demod('cqpsk', cqpsk_demod) | ||||
| 
 | ||||
							
								
								
									
										0
									
								
								src/demod/python/py_run_tests.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/demod/python/py_run_tests.in
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										69
									
								
								src/demod/python/tetra-demod.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								src/demod/python/tetra-demod.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| import sys | ||||
| import math | ||||
| from gnuradio import gr, gru, audio, eng_notation, blks2, optfir | ||||
| from gnuradio.eng_option import eng_option | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| # Load it locally or from the module | ||||
| try: | ||||
|     import cqpsk | ||||
| except: | ||||
|     from tetra_demod import cqpsk | ||||
| 
 | ||||
| # accepts an input file in complex format  | ||||
| # applies frequency translation, resampling (interpolation/decimation) | ||||
| 
 | ||||
| class my_top_block(gr.top_block): | ||||
|     def __init__(self): | ||||
|         gr.top_block.__init__(self) | ||||
|         parser = OptionParser(option_class=eng_option) | ||||
| 
 | ||||
|         parser.add_option("-c", "--calibration", type="int", default=-40000, help="freq offset") | ||||
|         parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") | ||||
|         parser.add_option("-l", "--log", action="store_true", default=False, help="dump debug .dat files") | ||||
|         parser.add_option("-L", "--low-pass", type="eng_float", default=25e3, help="low pass cut-off", metavar="Hz") | ||||
|         parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") | ||||
|         parser.add_option("-s", "--sample-rate", type="int", default=100000000/512, help="input sample rate") | ||||
|         parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") | ||||
|         (options, args) = parser.parse_args() | ||||
|   | ||||
|         sample_rate = options.sample_rate | ||||
|         symbol_rate = 18000 | ||||
|         sps = 2 | ||||
|         # output rate will be 36,000 | ||||
|         ntaps = 11 * sps | ||||
|         new_sample_rate = symbol_rate * sps | ||||
| 
 | ||||
|         channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) | ||||
| 
 | ||||
|         FILTER = gr.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, sample_rate) | ||||
| 
 | ||||
|         sys.stderr.write("sample rate: %d\n" %(sample_rate)) | ||||
| 
 | ||||
|         IN = gr.file_source(gr.sizeof_gr_complex, options.input_file) | ||||
| 
 | ||||
|         DEMOD = cqpsk.cqpsk_demod( samples_per_symbol = sps, | ||||
|                                  excess_bw=0.35, | ||||
|                                  costas_alpha=0.03, | ||||
|                                  gain_mu=0.05, | ||||
|                                  mu=0.05, | ||||
|                                  omega_relative_limit=0.05, | ||||
|                                  log=options.log, | ||||
|                                  verbose=options.verbose) | ||||
| 
 | ||||
| 
 | ||||
|         OUT = gr.file_sink(gr.sizeof_float, options.output_file) | ||||
| 
 | ||||
|         r = float(sample_rate) / float(new_sample_rate) | ||||
| 
 | ||||
|         INTERPOLATOR = gr.fractional_interpolator_cc(0, r) | ||||
| 
 | ||||
|         self.connect(IN, FILTER, INTERPOLATOR, DEMOD, OUT) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     try: | ||||
|         my_top_block().run() | ||||
|     except KeyboardInterrupt: | ||||
|         tb.stop() | ||||
							
								
								
									
										111
									
								
								src/demod/python/usrp1-tetra_demod.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										111
									
								
								src/demod/python/usrp1-tetra_demod.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| import sys | ||||
| import math | ||||
| from gnuradio import gr, gru, audio, eng_notation, blks2, optfir | ||||
| from gnuradio import usrp | ||||
| from gnuradio.eng_option import eng_option | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| try: | ||||
|     import cqpsk | ||||
| except: | ||||
|     from tetra_demod import cqpsk | ||||
| 
 | ||||
| # applies frequency translation, resampling (interpolation/decimation) and cqpsk demodulation | ||||
| 
 | ||||
| class my_top_block(gr.top_block): | ||||
|     def __init__(self, options): | ||||
|         gr.top_block.__init__(self) | ||||
| 
 | ||||
|         fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096) | ||||
|         fusb_nblocks    = gr.prefs().get_long('fusb', 'nblocks', 16) | ||||
|         self._u = usrp.source_c(decim_rate=options.decim, fusb_block_size=fusb_block_size, fusb_nblocks=fusb_nblocks) | ||||
| 
 | ||||
|         if options.rx_subdev_spec is None: | ||||
|             #options.rx_subdev_spec = pick_subdevice(self._u) | ||||
|             options.rx_subdev_spec = (0, 0) | ||||
| 
 | ||||
|         self._u.set_mux(usrp.determine_rx_mux_value(self._u, options.rx_subdev_spec)) | ||||
|         # determine the daughterboard subdevice | ||||
|         self.subdev = usrp.selected_subdev(self._u, options.rx_subdev_spec) | ||||
| 
 | ||||
|         # set initial values | ||||
|         if options.gain is None: | ||||
|             # if no gain was specified, use the mid-point in dB | ||||
|             g = self.subdev.gain_range() | ||||
|             options.gain = float(g[0]+g[1])/2 | ||||
| 
 | ||||
|         r = self._u.tune(0, self.subdev, options.freq) | ||||
|         self.subdev.set_gain(options.gain) | ||||
| 
 | ||||
|         #sample_rate = options.fpga_clock/options.decim | ||||
|         sample_rate = self._u.adc_freq() / self._u.decim_rate() | ||||
|         symbol_rate = 18000 | ||||
|         sps = 2 | ||||
|         # output rate will be 36,000 | ||||
|         ntaps = 11 * sps | ||||
|         new_sample_rate = symbol_rate * sps | ||||
| 
 | ||||
|         channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) | ||||
| 
 | ||||
|         FILTER = gr.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, sample_rate) | ||||
| 
 | ||||
|         sys.stderr.write("sample rate: %d\n" %(sample_rate)) | ||||
| 
 | ||||
|         DEMOD = cqpsk.cqpsk_demod( samples_per_symbol = sps, | ||||
|                                  excess_bw=0.35, | ||||
|                                  costas_alpha=0.03, | ||||
|                                  gain_mu=0.05, | ||||
|                                  mu=0.05, | ||||
|                                  omega_relative_limit=0.05, | ||||
|                                  log=options.log, | ||||
|                                  verbose=options.verbose) | ||||
| 
 | ||||
|         OUT = gr.file_sink(gr.sizeof_float, options.output_file) | ||||
| 
 | ||||
|         r = float(sample_rate) / float(new_sample_rate) | ||||
| 
 | ||||
|         INTERPOLATOR = gr.fractional_interpolator_cc(0, r) | ||||
| 
 | ||||
|         self.connect(self._u, FILTER, INTERPOLATOR, DEMOD, OUT) | ||||
| 
 | ||||
| def get_options(): | ||||
|     parser = OptionParser(option_class=eng_option) | ||||
| 
 | ||||
|     # usrp related settings | ||||
|     parser.add_option("-d", "--decim", type="int", default=250, | ||||
|                       help="Set USRP decimation rate to DECIM [default=%default]") | ||||
|     parser.add_option("-f", "--freq", type="eng_float", default=None, | ||||
|                       help="set frequency to FREQ", metavar="FREQ") | ||||
|     parser.add_option("-g", "--gain", type="eng_float", default=None, | ||||
|                       help="set gain in dB (default is midpoint)") | ||||
|     parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, | ||||
|                       help="Select USRP Rx side A or B (default=first one with a daughterboard)") | ||||
| 
 | ||||
|     # demodulator related settings | ||||
|     parser.add_option("-c", "--calibration", type="int", default=0, help="freq offset") | ||||
|     parser.add_option("-l", "--log", action="store_true", default=False, help="dump debug .dat files") | ||||
|     parser.add_option("-L", "--low-pass", type="eng_float", default=25e3, help="low pass cut-off", metavar="Hz") | ||||
|     parser.add_option("-o", "--output-file", type="string", default="out.float", help="specify the bit output file") | ||||
|     parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") | ||||
| 
 | ||||
|     (options, args) = parser.parse_args() | ||||
|     if len(args) != 0: | ||||
|         parser.print_help() | ||||
|         raise SystemExit, 1 | ||||
|      | ||||
|     if options.freq is None: | ||||
|         parser.print_help() | ||||
|         sys.stderr.write('You must specify the frequency with -f FREQ\n'); | ||||
|         raise SystemExit, 1 | ||||
|      | ||||
|     return (options) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     (options) = get_options() | ||||
|     tb = my_top_block(options) | ||||
|     try: | ||||
|         tb.run() | ||||
|     except KeyboardInterrupt: | ||||
|         tb.stop() | ||||
							
								
								
									
										112
									
								
								src/demod/python/usrp2-tetra_demod.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										112
									
								
								src/demod/python/usrp2-tetra_demod.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| import sys | ||||
| import math | ||||
| from gnuradio import gr, gru, audio, eng_notation, blks2, optfir | ||||
| from gnuradio import usrp2 | ||||
| from gnuradio.eng_option import eng_option | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| # Load it locally or from the module | ||||
| try: | ||||
|     import cqpsk | ||||
| except: | ||||
|     from tetra_demod import cqpsk | ||||
| 
 | ||||
| # accepts an input file in complex format  | ||||
| # applies frequency translation, resampling (interpolation/decimation) | ||||
| 
 | ||||
| class my_top_block(gr.top_block): | ||||
|     def __init__(self, options): | ||||
|         gr.top_block.__init__(self) | ||||
| 
 | ||||
|         # Create a USRP2 source and set decimation rate | ||||
|         self._u = usrp2.source_32fc(options.interface, options.mac_addr) | ||||
|         self._u.set_decim(512) | ||||
| 
 | ||||
|         # Set receive daughterboard gain | ||||
|         if options.gain is None: | ||||
|             g = self._u.gain_range() | ||||
|             options.gain = float(g[0]+g[1])/2 | ||||
|             print "Using mid-point gain of", options.gain, "(", g[0], "-", g[1], ")" | ||||
|         self._u.set_gain(options.gain) | ||||
|   | ||||
|         # Set receive frequency | ||||
|         if options.lo_offset is not None: | ||||
|             self._u.set_lo_offset(options.lo_offset) | ||||
| 
 | ||||
|         tr = self._u.set_center_freq(options.freq) | ||||
|         if tr == None: | ||||
|             sys.stderr.write('Failed to set center frequency\n') | ||||
|             raise SystemExit, 1 | ||||
| 
 | ||||
|         sample_rate = 100e6/512 | ||||
|         symbol_rate = 18000 | ||||
|         sps = 2 | ||||
|         # output rate will be 36,000 | ||||
|         ntaps = 11 * sps | ||||
|         new_sample_rate = symbol_rate * sps | ||||
| 
 | ||||
|         channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) | ||||
| 
 | ||||
|         FILTER = gr.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, sample_rate) | ||||
| 
 | ||||
|         sys.stderr.write("sample rate: %d\n" %(sample_rate)) | ||||
| 
 | ||||
|         DEMOD = cqpsk.cqpsk_demod( samples_per_symbol = sps, | ||||
|                                  excess_bw=0.35, | ||||
|                                  costas_alpha=0.03, | ||||
|                                  gain_mu=0.05, | ||||
|                                  mu=0.05, | ||||
|                                  omega_relative_limit=0.05, | ||||
|                                  log=options.log, | ||||
|                                  verbose=options.verbose) | ||||
| 
 | ||||
|         OUT = gr.file_sink(gr.sizeof_float, options.output_file) | ||||
| 
 | ||||
|         r = float(sample_rate) / float(new_sample_rate) | ||||
| 
 | ||||
|         INTERPOLATOR = gr.fractional_interpolator_cc(0, r) | ||||
| 
 | ||||
|         self.connect(self._u, FILTER, INTERPOLATOR, DEMOD, OUT) | ||||
| 
 | ||||
| def get_options(): | ||||
|     parser = OptionParser(option_class=eng_option) | ||||
|     # usrp related settings | ||||
|     parser.add_option("-e", "--interface", type="string", default="eth0", | ||||
|                       help="use specified Ethernet interface [default=%default]") | ||||
|     parser.add_option("-m", "--mac-addr", type="string", default="", | ||||
|                       help="use USRP2 at specified MAC address [default=None]")   | ||||
|     parser.add_option("-f", "--freq", type="eng_float", default=None, | ||||
|                       help="set frequency to FREQ", metavar="FREQ") | ||||
|     parser.add_option("-g", "--gain", type="eng_float", default=None, | ||||
|                       help="set gain in dB (default is midpoint)") | ||||
|     parser.add_option("", "--lo-offset", type="eng_float", default=None, | ||||
|                       help="set daughterboard LO offset to OFFSET [default=hw default]") | ||||
| 
 | ||||
|     # demodulator related settings | ||||
|     parser.add_option("-c", "--calibration", type="int", default=0, help="freq offset") | ||||
|     parser.add_option("-l", "--log", action="store_true", default=False, help="dump debug .dat files") | ||||
|     parser.add_option("-L", "--low-pass", type="eng_float", default=25e3, help="low pass cut-off", metavar="Hz") | ||||
|     parser.add_option("-o", "--output-file", type="string", default="out.float", help="specify the bit output file") | ||||
|     parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") | ||||
| 
 | ||||
|     (options, args) = parser.parse_args() | ||||
|     if len(args) != 0: | ||||
|         parser.print_help() | ||||
|         raise SystemExit, 1 | ||||
|      | ||||
|     if options.freq is None: | ||||
|         parser.print_help() | ||||
|         sys.stderr.write('You must specify the frequency with -f FREQ\n'); | ||||
|         raise SystemExit, 1 | ||||
|      | ||||
|     return (options) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     (options) = get_options() | ||||
|     tb = my_top_block(options) | ||||
|     try: | ||||
|         tb.run() | ||||
|     except KeyboardInterrupt: | ||||
|         tb.stop() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Harald Welte
						Harald Welte