├── .gitignore ├── CMakeLists.txt ├── ChanList.csv ├── README.md ├── audio_receiver_dsd.cc ├── audio_receiver_dsd.h ├── cmake └── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── FindGnuradioAudio.cmake │ ├── FindGnuradioCore.cmake │ ├── FindGnuradioFCD.cmake │ ├── FindGnuradioFCDPP.cmake │ ├── FindGnuradioIQBalance.cmake │ ├── FindGnuradioUHD.cmake │ ├── FindGruel.cmake │ ├── FindLibDSD.cmake │ ├── FindLibDSD.cmake~ │ ├── FindLibHackRF.cmake │ ├── FindLibMiriSDR.cmake │ ├── FindLibOsmoSDR.cmake │ ├── FindLibOsmoSDR.cmake~ │ ├── FindLibRTLSDR.cmake │ ├── FindLibbladeRF.cmake │ ├── FindUHD.cmake │ ├── GrComponent.cmake │ ├── GrMiscUtils.cmake │ ├── GrPlatform.cmake │ ├── GrPython.cmake │ ├── GrSwig.cmake │ ├── GrTest.cmake │ └── GrVersion.cmake ├── dsd_block_ff.h ├── example_start.sh ├── fsk_demod.cc ├── fsk_demod.h ├── scanner.png ├── smartnet.cc ├── smartnet_crc.cc ├── smartnet_crc.h ├── smartnet_deinterleave.cc ├── smartnet_deinterleave.h ├── smartnet_types.h ├── talkgroup.cc └── talkgroup.h /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | Makefile 4 | cmake_install.cmake 5 | install_manifest.txt 6 | -------------------------------------------------------------------------------- /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 | cmake_minimum_required(VERSION 2.6) 23 | project(gr-osmosdr CXX C) 24 | 25 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) 26 | 27 | ######################################################################## 28 | # Find build dependencies 29 | ######################################################################## 30 | find_package(Gruel) 31 | find_package(GnuradioCore) 32 | find_package(GnuradioIQBalance) 33 | find_package(UHD) 34 | find_package(GnuradioUHD) 35 | find_package(GnuradioFCD) 36 | find_package(GnuradioFCDPP) 37 | find_package(LibOsmoSDR) 38 | find_package(LibRTLSDR) 39 | find_package(LibMiriSDR) 40 | find_package(LibHackRF) 41 | find_package(LibbladeRF) 42 | #find_package(LibDSD) 43 | 44 | if(NOT GRUEL_FOUND) 45 | message(FATAL_ERROR "Gruel required to build " ${CMAKE_PROJECT_NAME}) 46 | endif() 47 | 48 | if(NOT GNURADIO_CORE_FOUND) 49 | message(FATAL_ERROR "GnuRadio Core required to build " ${CMAKE_PROJECT_NAME}) 50 | endif() 51 | 52 | 53 | ######################################################################## 54 | # Setup boost 55 | ######################################################################## 56 | MESSAGE(STATUS "Configuring Boost C++ Libraries...") 57 | 58 | # Although not required on my system, some users have linking issues without 59 | SET(BOOST_REQUIRED_COMPONENTS 60 | thread 61 | system 62 | program_options 63 | ) 64 | 65 | if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") 66 | list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix 67 | endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") 68 | 69 | set(Boost_ADDITIONAL_VERSIONS 70 | "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" 71 | "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" 72 | "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" 73 | "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" 74 | "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" 75 | "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" 76 | "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" 77 | ) 78 | 79 | find_package(Boost COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) 80 | 81 | if(NOT Boost_FOUND) 82 | message(FATAL_ERROR "Boost required to build " ${CMAKE_PROJECT_NAME}) 83 | endif() 84 | 85 | ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) 86 | 87 | 88 | ######################################################################## 89 | # Register component 90 | ######################################################################## 91 | #include(GrComponent) 92 | #GR_REGISTER_COMPONENT("gr-audio" ENABLE_GR_AUDIO 93 | # Boost_FOUND 94 | # ENABLE_GR_CORE 95 | #) 96 | 97 | 98 | 99 | 100 | SET(GR_PKG_AUDIO_EXAMPLES_DIR .) 101 | 102 | 103 | 104 | ######################################################################## 105 | # Setup the include and linker paths 106 | ######################################################################## 107 | include_directories( 108 | ${Boost_INCLUDE_DIRS} 109 | ${GRUEL_INCLUDE_DIRS} 110 | ${GNURADIO_CORE_INCLUDE_DIRS} 111 | ${LIBOSMOSDR_INCLUDE_DIR} 112 | ${LIBDSD_INCLUDE_DIR} 113 | /usr/local/include/dsd/ 114 | ) 115 | 116 | link_directories( 117 | ${Boost_LIBRARY_DIRS} 118 | ${GRUEL_LIBRARY_DIRS} 119 | ${GNURADIO_CORE_LIBRARY_DIRS} 120 | ${LIBOSMOSDR_LIBRARIES} 121 | ${LIBDSD_LIBRARIES} 122 | /usr/local/lib/ 123 | ) 124 | 125 | 126 | add_executable(smartnet smartnet.cc smartnet_crc.cc smartnet_deinterleave.cc audio_receiver_dsd.cc talkgroup.cc) 127 | target_link_libraries(smartnet gnuradio-core gnuradio-audio gnuradio-blocks gnuradio-osmosdr gnuradio-filter gnuradio-digital gnuradio-analog ${GRUEL_LIBRARIES} ${Boost_LIBRARIES} gr-dsd ncurses menu) 128 | 129 | INSTALL(TARGETS 130 | smartnet 131 | DESTINATION ${GR_PKG_AUDIO_EXAMPLES_DIR} 132 | COMPONENT "audio_examples" 133 | ) 134 | -------------------------------------------------------------------------------- /ChanList.csv: -------------------------------------------------------------------------------- 1 | 1616,65,D,DCFD 01 Disp,01 Dispatch,Fire Dispatch,Fire/EMS 2 | 1632,66,D,DCFD 02 Main,02 Main,Fire-Tac,Fire/EMS 3 | 1648,67,D,DCFD 03,03 Fireground 3,Fire-Tac,Fire/EMS 4 | 1680,69,D,DCFD 05,05 Fireground 5,Fire-Tac,Fire/EMS 5 | 1696,06a,D,DCFD 06,06 Fireground 1A,Fire-Tac,Fire/EMS 6 | 1712,06b,D,DCFD 07,07 Fireground 7,Fire-Tac,Fire/EMS 7 | 1744,06d,D,DCFD 09,09 Fireground 9,Fire-Tac,Fire/EMS 8 | 1760,6,D,DCFD 010,010 Fireground 2A,Fire-Tac,Fire/EMS 9 | 1776,06f,D,DCFD 0A3,0A3 Fireground A3,Fire-Tac,Fire/EMS 10 | 1808,71,D,DCFD 0A5,0A5 Fireground A5,Fire-Tac,Fire/EMS 11 | 1824,72,D,DCFD 0A6,0A6 Fireground 3A,Fire-Tac,Fire/EMS 12 | 1840,73,D,DCFD 0A7,0A7 Fireground A7,Fire-Tac,Fire/EMS 13 | 1872,75,D,DCFD 0A9,0A9 Fireground A9,Fire-Tac,Fire/EMS 14 | 1888,76,D,DCFD 0A10,0A10 Fireground 4A,Fire-Tac,Fire/EMS 15 | 1904,77,D,DCFD 011 EM1,011 EMS 1,EMS-Tac,Fire/EMS 16 | 1920,78,D,DCFD 012 EM2,012 EMS 2,EMS-Tac,Fire/EMS 17 | 1936,79,D,DCFD 013 EM3,013 EMS 3,EMS-Talk,Fire/EMS 18 | 1952,07a,D,DCFD NCR,National Capital Region (sometimes encrypted),Interop,Fire/EMS 19 | 1968,07b,D,DCFD 0B10,0B10 Fireground 6A,Fire-Tac,Fire/EMS 20 | 2000,07d,D,DCFD 0C4 App,0C4 Apparatus Division,Fire-Talk,Fire/EMS 21 | 2016,7,D,DCFD 0B3,0B3 Rescue Assignments,Fire-Tac,Fire/EMS 22 | 2048,80,D,DCFD 0C11 Tr,0C11 Training Administration,Fire-Tac,Fire/EMS 23 | 2064,81,D,DCFD 0C6 Inv,0C6 Investigations,Fire-Tac,Fire/EMS 24 | 2080,82,D,DCFD 0C5 Ins,0C5 Inspectors,Fire-Tac,Fire/EMS 25 | 2096,83,D,DCFD 0A11 SE,0A11 Special Event 1,Fire-Tac,Fire/EMS 26 | 2112,84,D,DCFD 0A12 SE,0A12 Special Event 2,Fire-Tac,Fire/EMS 27 | 2128,85,D,DCFD 0A13 SE,0A13 Special Event 3,Fire-Tac,Fire/EMS 28 | 2144,86,D,DCFD 0C3 Log,0C3 Logistics,Fire-Tac,Fire/EMS 29 | 2160,87,D,DCFD 0B12,0B12 Patch 1,Fire-Tac,Fire/EMS 30 | 2176,88,D,DCFD 0B13,0B13 Patch 2,Fire-Tac,Fire/EMS 31 | 2192,89,D,DCFD 0B14,0B14 Stage B,Fire-Tac,Fire/EMS 32 | 2224,08b,D,DCFD 0B9,0B9 Fireground,Fire-Tac,Fire/EMS 33 | 2240,08c,D,DCFD 0C8 SpO,0C8 Special Operations,Fire-Tac,Fire/EMS 34 | 2272,8,D,DCFD 0H1 UMC,0H1 United Medical Center,Hospital,Fire/EMS 35 | 2288,08f,D,DCFD 0H2 Chd,0H2 Children's,Hospital,Fire/EMS 36 | 2304,90,D,DCFD 0H3,0H3 Spare,Hospital,Fire/EMS 37 | 2320,91,D,DCFD 0H4 MST,0H4 MedSTAR,Hospital,Fire/EMS 38 | 2336,92,D,DCFD 0H5 How,0H5 Howard University,Hospital,Fire/EMS 39 | 2352,93,D,DCFD 0H6 DCG,0H6 DC General,Hospital,Fire/EMS 40 | 2368,94,D,DCFD 0H7 GU,0H7 Georgetown University,Hospital,Fire/EMS 41 | 2384,95,D,DCFD 0H8 GWU,0H8 George Washington University,Hospital,Fire/EMS 42 | 2400,96,D,DCFD 0H9,0H9 Children's at United Medical Center,Hospital,Fire/EMS 43 | 2416,97,D,DCFD 0H10 Pr,0H10 Providence,Hospital,Fire/EMS 44 | 2432,98,D,DCFD 0H11 PC,0H11 Poison Control,Hospital,Fire/EMS 45 | 2448,99,D,DCFD 0H12 Si,0H12 Sibley,Hospital,Fire/EMS 46 | 2464,09a,D,DCFD 0H13 WH,0H13 Washington Hospital Center,Hospital,Fire/EMS 47 | 2480,09b,D,DCFD 0H14 WR,0H14 Walter Reed,Hospital,Fire/EMS 48 | 2496,09c,D,DCFD 0H15 Vt,0H15 Veterans,Hospital,Fire/EMS 49 | 2512,09d,D,DCFD 0H16 PG,0H16 Prince George's,Hospital,Fire/EMS 50 | 2592,0a2,D,DCFD 0C7 MPD,0C7 MPD-DCFD Interoperability,Interop,Fire/EMS 51 | 2608,0a3,D,DCFD 0C15,0C15 Admin 2,Fire-Talk,Fire/EMS 52 | 2640,0a5,D,DCFD 0C9 FBt,0C9 Fire Boat,Fire-Tac,Fire/EMS 53 | 2656,0a6,D,DC-01 UCC1,Unified Communications Center 1,Interop,DC Common 54 | 2672,0a7,D,DC-02 UCC2,Unified Communications Center 2,Interop,DC Common 55 | 2720,0aa,D,DCFD 014,014 Stage 0,Fire-Tac,Fire/EMS 56 | 2736,0ab,D,DCFD 0A14,0A14 Stage A,Fire-Tac,Fire/EMS 57 | 2752,0ac,E,DCFD Encrypt,Encrypted,Fire-Talk,Fire/EMS 58 | 2848,0b2,D,DCFD 0C16,0C16 Admin 3,Fire-Tac,Fire/EMS 59 | 2864,0b3,D,DCFD 0B5,0B5 Fireground,Fire-Tac,Fire/EMS 60 | 2880,0b4,D,DCFD 0B6,0B6 Fireground 5A,Fire-Tac,Fire/EMS 61 | 9808,265,D,DCFD 0G12,0G12 Tactical/Fireground 3,Fire-Tac,Fire/EMS 62 | 9824,266,D,DCFD 0C10,0C10 Spare,Fire-Tac,Fire/EMS 63 | 9840,267,D,DCFD 0B7,0B7 Ops Command,Fire-Tac,Fire/EMS 64 | 9872,269,D,DCFD 0C14,0C14 Admin 1,Fire-Tac,Fire/EMS 65 | 9936,26d,D,DC-07 MAF1,Mutual Aid Fire 1,Interop,DC Common 66 | 9968,26f,D,DC-08 MAF2,Mutual Aid Fire 2,Interop,DC Common 67 | 9984,270,D,DCFD MAF3,Mutual Aid Fire 3,Interop,Fire/EMS 68 | 10032,273,D,DCFD MAF4,Mutual Aid Fire 4,Interop,Fire/EMS 69 | 16624,40f,D,DC-16 CW-1,MPD Citywide 1,Law Dispatch,DC Common 70 | 19248,4b3,D,DC-13 PMARS,Police Mutual Aid Radio System (PMARS),Interop,DC Common 71 | 33584,833,D,DC Hlth Tac,Department of Health Tac,Public Works,Services 72 | 33616,835,D,DC-11 Exec1,Executive 1 (Senior City Officials),Interop,DC Common 73 | 33648,837,D,DC-12 Exec2,Executive 2 (City Officials),Interop,DC Common 74 | 33840,843,D,DC ReeveSec?,Reeves Center Security?,Public Works,Services 75 | 33872,845,D,DC EMA 33872,Emergency Management Agency,Emergency Ops,Services 76 | 33904,847,D,DC EMA 33904,Emergency Management Agency,Emergency Ops,Services 77 | 34128,855,D,DC Sch Sec,School Security,Security,Services 78 | 34192,859,D,DC Sec 34192,Security (Unknown Agency),Security,Services 79 | 34288,85f,D,StEliz Mnt,St. Elizabeth's Hospital - Maintenance/Motor Pool,Public Works,Services 80 | 34320,861,D,StEliz Ops 1,St. Elizabeth's Hospital - Ops 1,Public Works,Services 81 | 34352,863,D,StEliz Sec,St. Elizabeth's Hospital - Security,Security,Services 82 | 34384,865,D,StEliz Ops 2,St. Elizabeth's Hospital - Ops 2,Public Works,Services 83 | 34416,867,D,DC DHS Ops,Department of Human Services Ops,Public Works,Services 84 | 34448,869,D,DC Health,Department of Health,Public Works,Services 85 | 34480,86b,D,DC Med Exam,Office of the Chief Medical Examiner (OCME),Public Works,Services 86 | 34512,86d,D,DDOT TCO,Department of Transportation Traffic Control Officers,Public Works,Services 87 | 34576,871,D,DDOT 34576,Department of Transportation,Public Works,Services 88 | 34608,873,D,DC Pkg Enf,Parking Enforcement,Public Works,Services 89 | 34672,877,D,DC 34672,(Active during 2006 National Marathon),Public Works,Services 90 | 34800,87f,D,DC PkgEnf T2,Parking Enforcement Tac 2,Public Works,Services 91 | 34832,881,D,DC PrtSrvDsp,DC Protective Services Dispatch,Security,Services 92 | 34864,883,D,DC PrtSrvTac,DC Protective Services Tactical,Security,Services 93 | 35024,88d,D,DC WASA 1,Water and Sewer Authority 1,Public Works,Services 94 | 35056,88f,D,DC WASA 2,Water and Sewer Authority 2,Public Works,Services 95 | 35088,891,D,DC WASA 3,Water and Sewer Authority 3,Public Works,Services 96 | 35152,895,D,DC Lib Sec,Library Security,Security,Services 97 | 35184,897,D,DC 35184,Coordination of 2007 National Fire and Emergency Services Dinner and Seminars,Public Works,Services 98 | 35216,899,D,DC 35216,Coordination of 2007 National Fire and Emergency Services Dinner and Seminars--Shuttle,Public Works,Services 99 | 35248,89b,D,DC Parks&Rec,Parks and Recreation,Public Works,Services 100 | 35408,8a5,D,DC UDC PD,University of the District of Columbia Police,Law Dispatch,Services 101 | 35440,8a7,D,DC UDC PD T,University of the District of Columbia Police Tac,Law Tac,Services 102 | 35536,8ad,D,DC-09 EMA1,Emergency Management Agency 1,Interop,DC Common 103 | 35568,8af,D,DC-10 EMA2,Emergency Management Agency 2,Interop,DC Common 104 | 35600,8b1,D,DC TraffMgmt,Traffic Management Center (TMC),Public Works,Services 105 | 35664,8b5,D,DC Paratrans,Paratransit,Transportation,Services 106 | 36880,901,D,DC Hosp Roll,Hospital Roll Call,Hospital,Services 107 | 37040,90b,D,DC MotorPool,Motor Pool,Public Works,Services 108 | 37200,915,D,DC MPD FlMt?,MPD Fleet Maintenance?,Public Works,Services 109 | 37232,917,D,DC UDC PD T,University of the District of Columbia Police Tac,Law Tac,Services 110 | 37328,91d,D,DC Pub Work?,Public Works?,Public Works,Services 111 | 37456,925,D,DC-03 UCC3,Unified Communications Center 3,Interop,DC Common 112 | 37488,927,D,DC-04 UCC4,Unified Communications Center 4,Interop,DC Common 113 | 37648,931,D,DC-14 Spare1,Spare 1,Interop,DC Common 114 | 37680,933,D,DC-15 Spare2,Spare 2,Interop,DC Common 115 | 40000,9c4,D,DCFD AutoDsp,Automated Dispatch,Fire Dispatch,Fire/EMS 116 | 40032,9c6,D,DCFD AutoDsp,Automated Dispatch,Fire Dispatch,Fire/EMS 117 | 40080,9c9,D,DC Taxi Comm,Taxicab Commission,Public Works,Services 118 | 56000,dac,A,DCFD MOSCAD,MOSCAD Data,Data,Fire/EMS 119 | 56016,dad,A,DCFD MOSCAD,MOSCAD Data,Data,Fire/EMS 120 | 59952,ea3,D,DC-05 MA1,Mutual Aid 1,Interop,DC Common 121 | 59968,ea4,D,DC-06 MA2,Mutual Aid 2 (also DC Interop 1),Interop,DC Common 122 | 59984,ea5,D,MPD MA3,Mutual Aid 3,Interop,Police 123 | 60000,ea6,D,MPD MA4,Mutual Aid 4,Interop,Police 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Smartnet Scanner 2 | 3 | ![](//scanner.png) 4 | 5 | GNURadio based scanner for SmartNet II Digital radio systems. It is for systems that use P25 CAI for the voice channels instead of analog. 6 | 7 | ### Channel List 8 | In order to work, the scanner needs a list of the talkgroups on the system. This is stored in a Comma Sperated Value (CSV) file, that should be named ChanList.csv. 9 | 10 | In order to get this data: 11 | 12 | 1. Goto [Radio Reference](http://www.radioreference.com/apps/db/) and find the system. 13 | 2. Click on "List All in one table". 14 | 3. Select the tabel and copy it into a spreadsheet program like Excel, or Google Docs. 15 | 4. It should have 7 different columns. 16 | 5. The value in the collumns should be as follows: 17 | `DEC - HEX - Mode - Alpha Tag - Description - Tag - Group` 18 | 6. Save this file in the CSV format. 19 | 20 | ### Installation 21 | **Requirements** 22 | - GNURadio 3.6 23 | - My version of [gr-dsd](https://github.com/robotastic/gr-dsd) 24 | 25 | Once all this is installed then 26 | 27 | cmake . 28 | make 29 | 30 | ### Parameters 31 | Here are the options available for the scanner. I put the parameters I use in _examplestart.sh_. 32 | 33 | ./smartnet --freq 856187500.0 --center 857000000.0 --rate 8000000 --error -5500 --rfgain 14 --ifgain 35 --bbgain 35 34 | 35 | 36 | **--rfgain** _14_ 37 | 38 | This is the standard gain that you usually set with your SDR program. For the HackRF, it is either on or off. To turn it one, set it to 14. 39 | 40 | **--ifgain** _35_ 41 | 42 | This is an additional gain option that is useful for the HackRF, but may not be set able with SDR. 43 | 44 | 45 | **--bbgain** _35_ 46 | 47 | This is an additional gain option that is useful for the HackRF, but may not be set able with SDR. 48 | 49 | 50 | **--rate** _4000000_ 51 | 52 | This is the sample rate that will be used. You want to make sure that the sampling rate you pick is equal to or large than the range of frequencies used by the radio system you are monitoring. Try to make it as small as possible though or else things will be slow because you will have to process lots of extra data. 53 | 54 | 55 | **--center** _857000000.0_ 56 | 57 | This is the center frequency that the SDR will be tuned to. It should be in middle of the lowest frequency and the highest frequency of the system you are trying to monitor. There is usally a spike at the center, so make sure you don't have the center freq landing on one of the channels in the radio system. 58 | 59 | 60 | **--freq** _856187500.0_ 61 | 62 | This is the SmartNet control channel frequency for the system you monitoring. This program will listen to it and track the different channel assignments for the talkgroups. Check [Radio Reference](http://www.radioreference.com/apps/db/) to find this frequency. 63 | 64 | 65 | **--error** _-5500_ 66 | 67 | SDRs are great, but the tuning is always off by a little unless you have an external clock. This setting lets you correct for this error. The amount of error will generally be different for each device. For my HackRF, I have found the amount of error to be pretty stable though. However it is different at different spots in the sprectrum, so figure it out for each system you are looking at. In order to find yours, fire up a program like [GQRX](http://gqrx.dk/), tune in the control channel for the system you want to monitor and determine how far it is off from the specified frequency. Note: the frequency tuned in is actuall calculated as: _target - error_. So for with system it was: Target = 856187500.0 and Actual = 85619300.0, so the error was: Target - Actual = -5500. 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /audio_receiver_dsd.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "audio_receiver_dsd.h" 3 | 4 | log_dsd_sptr make_log_dsd(float freq, float center, long t, long rate) 5 | { 6 | return gnuradio::get_initial_sptr(new log_dsd(freq, center, t, rate)); 7 | } 8 | unsigned GCD(unsigned u, unsigned v) { 9 | while ( v != 0) { 10 | unsigned r = u % v; 11 | u = v; 12 | v = r; 13 | } 14 | return u; 15 | } 16 | 17 | std::vector design_filter(double interpolation, double deci) { 18 | float beta = 5.0; 19 | float trans_width = 0.5 - 0.4; 20 | float mid_transition_band = 0.5 - trans_width/2; 21 | 22 | std::vector result = gr_firdes::low_pass( 23 | interpolation, 24 | 1, 25 | mid_transition_band/interpolation, 26 | trans_width/interpolation, 27 | gr_firdes::WIN_KAISER, 28 | beta 29 | ); 30 | 31 | return result; 32 | } 33 | log_dsd::log_dsd(float f, float c, long t, long r) 34 | : gr_hier_block2 ("log_dsd", 35 | gr_make_io_signature (1, 1, sizeof(gr_complex)), 36 | gr_make_io_signature (0, 0, sizeof(float))) 37 | { 38 | freq = f; 39 | center = c; 40 | talkgroup = t; 41 | samp_rate = r; 42 | float offset = center - (f*1000000); 43 | char filename[160]; 44 | int samp_per_sym = 10; 45 | int decim = int(samp_rate/50000); 46 | float xlate_bandwidth = 14000; //24260.0; 47 | float channel_rate = 4800 * samp_per_sym; 48 | double pre_channel_rate = double(samp_rate/decim); 49 | double vocoder_rate = 8000; 50 | double audio_rate = 44100; 51 | 52 | timestamp = time(NULL); 53 | 54 | 55 | 56 | 57 | 58 | prefilter = gr_make_freq_xlating_fir_filter_ccf(decim, 59 | gr_firdes::low_pass(1, samp_rate, xlate_bandwidth/2, 6000), 60 | offset, 61 | samp_rate); 62 | 63 | unsigned int d = GCD(channel_rate, pre_channel_rate); 64 | channel_rate = floor(channel_rate / d); 65 | pre_channel_rate = floor(pre_channel_rate / d); 66 | 67 | downsample_sig = gr_make_rational_resampler_base_ccf(channel_rate, pre_channel_rate, design_filter(channel_rate, pre_channel_rate)); 68 | 69 | 70 | 71 | 72 | d = GCD(audio_rate, vocoder_rate); 73 | audio_rate = floor(audio_rate / d); 74 | vocoder_rate = floor(vocoder_rate / d); 75 | upsample_audio = gr_make_rational_resampler_base_fff(audio_rate, vocoder_rate, design_filter(audio_rate, vocoder_rate)); 76 | 77 | 78 | demod = gr_make_quadrature_demod_cf(1.6); 79 | 80 | const float a[] = { 0.1, 0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1}; 81 | 82 | std::vector data( a,a + sizeof( a ) / sizeof( a[0] ) ); 83 | sym_filter = gr_make_fir_filter_fff(1, data); 84 | dsd = dsd_make_block_ff(dsd_FRAME_P25_PHASE_1,dsd_MOD_AUTO_SELECT,3,0,0, true); 85 | null_sink = gr_make_null_sink(sizeof(gr_complex)); 86 | null_source = gr_make_null_source(sizeof(gr_complex)); 87 | copier = gr_make_kludge_copy(sizeof(gr_complex)); 88 | head_source = gr_make_head(sizeof(gr_complex),0); 89 | sprintf(filename, "%ld-%ld.wav", talkgroup,timestamp); 90 | audio_sink::sptr sink = audio_make_sink(44100); 91 | 92 | //connect(self(), 0, prefilter, 0); 93 | 94 | 95 | //start off muted 96 | 97 | connect(self(), 0, null_sink, 0); 98 | connect(null_source,0,head_source,0); 99 | connect(head_source,0,prefilter,0); 100 | muted = true; 101 | 102 | connect(prefilter, 0, downsample_sig, 0); 103 | connect(downsample_sig, 0, demod, 0); 104 | connect(demod, 0, sym_filter, 0); 105 | connect(sym_filter, 0, dsd, 0); 106 | //connect(dsd, 0, wav_sink,0); 107 | 108 | 109 | connect(dsd, 0, upsample_audio,0); 110 | connect(upsample_audio, 0, sink,0); 111 | //connect(sym_filter,0,fs,0); 112 | } 113 | 114 | log_dsd::~log_dsd() { 115 | 116 | } 117 | 118 | void log_dsd::active() { 119 | timestamp = time(NULL); 120 | } 121 | 122 | // from: /gnuradio/grc/grc_gnuradio/blks2/selector.py 123 | void log_dsd::unmute() { 124 | // this function gets called everytime their is a TG continuation command. This keeps the timestamp updated. 125 | timestamp = time(NULL); 126 | if (muted) { 127 | 128 | disconnect(self(),0, null_sink,0); 129 | disconnect(head_source,0, prefilter,0); 130 | connect(head_source,0, null_sink,0); 131 | connect(self(),0, copier,0); 132 | connect(copier,0, prefilter,0); 133 | //connect(self(),0, prefilter,0); 134 | muted = false; 135 | } 136 | } 137 | 138 | void log_dsd::mute() { 139 | 140 | if (!muted) { 141 | 142 | //disconnect(self(),0, prefilter,0); 143 | 144 | disconnect(self(),0, copier,0); 145 | disconnect(copier,0, prefilter,0); 146 | disconnect(head_source,0, null_sink,0); 147 | 148 | connect(head_source,0,prefilter,0); 149 | connect(self(),0, null_sink,0); 150 | muted = true; 151 | } 152 | } 153 | 154 | long log_dsd::get_talkgroup() { 155 | return talkgroup; 156 | } 157 | 158 | void log_dsd::set_talkgroup(long tg) { 159 | talkgroup = tg; 160 | } 161 | 162 | float log_dsd::get_freq() { 163 | return freq; 164 | } 165 | 166 | long log_dsd::rx_timeout() { 167 | return time(NULL) - timestamp; 168 | } 169 | 170 | void log_dsd::close() { 171 | mute(); 172 | //wav_sink->close(); 173 | } 174 | 175 | /* 176 | void log_dsd::forecast(int noutput_items, gr_vector_int &ninput_items_required) { 177 | ninput_items_required[0] = 4 * noutput_items; 178 | }*/ 179 | 180 | 181 | void log_dsd::tune_offset(float f) { 182 | freq = f; 183 | prefilter->set_center_freq(center - (f*1000000)); 184 | //std::cout << "Offset set to: " << (f*1000000-center) << std::endl; 185 | } 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /audio_receiver_dsd.h: -------------------------------------------------------------------------------- 1 | #ifndef LPF_H 2 | #define LPF_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "dsd_block_ff.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | //Valve 32 | #include 33 | #include 34 | #include 35 | #include 36 | //#include 37 | //#include 38 | //#include 39 | 40 | class log_dsd; 41 | 42 | typedef boost::shared_ptr log_dsd_sptr; 43 | 44 | log_dsd_sptr make_log_dsd(float f, float c, long t, long r); 45 | 46 | class log_dsd : public gr_hier_block2 47 | { 48 | friend log_dsd_sptr make_log_dsd(float f, float c, long t, long r); 49 | protected: 50 | log_dsd(float f, float c, long t, long r); 51 | 52 | public: 53 | ~log_dsd(); 54 | void tune_offset(float f); 55 | float get_freq(); 56 | long get_talkgroup(); 57 | void set_talkgroup(long tg); 58 | long rx_timeout(); 59 | void close(); 60 | void mute(); 61 | void unmute(); 62 | void active(); 63 | //void forecast(int noutput_items, gr_vector_int &ninput_items_required); 64 | 65 | private: 66 | float center, freq; 67 | bool muted; 68 | long talkgroup; 69 | double samp_rate; 70 | time_t timestamp; 71 | 72 | 73 | /* GR blocks */ 74 | gr_fir_filter_ccf_sptr lpf; 75 | gr_fir_filter_fff_sptr sym_filter; 76 | gr_freq_xlating_fir_filter_ccf_sptr prefilter; 77 | gr_sig_source_c_sptr offset_sig; 78 | 79 | gr_multiply_cc_sptr mixer; 80 | gr_file_sink_sptr fs; 81 | 82 | gr_rational_resampler_base_ccf_sptr downsample_sig; 83 | gr_rational_resampler_base_fff_sptr upsample_audio; 84 | //gr::analog::quadrature_demod_cf::sptr demod; 85 | gr_quadrature_demod_cf_sptr demod; 86 | dsd_block_ff_sptr dsd; 87 | audio_sink::sptr sink; 88 | //smartnet_wavsink_sptr wav_sink 89 | //gr::blocks::wavfile_sink::sptr wav_sink; 90 | gr_null_sink_sptr null_sink; 91 | gr_null_source_sptr null_source; 92 | gr_head_sptr head_source; 93 | gr_kludge_copy_sptr copier; 94 | 95 | }; 96 | 97 | 98 | #endif 99 | 100 | -------------------------------------------------------------------------------- /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/FindGnuradioAudio.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_AUDIO gnuradio-audio) 3 | 4 | FIND_PATH( 5 | GNURADIO_AUDIO_INCLUDE_DIRS 6 | NAMES gnuradio/gr_audio_api.h 7 | HINTS $ENV{GNURADIO_AUDIO_DIR}/include 8 | ${PC_GNURADIO_AUDIO_INCLUDEDIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GNURADIO_AUDIO_LIBRARIES 15 | NAMES gnuradio-audio 16 | HINTS $ENV{GNURADIO_AUDIO_DIR}/lib 17 | ${PC_GNURADIO_AUDIO_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_AUDIO DEFAULT_MSG GNURADIO_AUDIO_LIBRARIES GNURADIO_AUDIO_INCLUDE_DIRS) 26 | MARK_AS_ADVANCED(GNURADIO_AUDIO_LIBRARIES GNURADIO_AUDIO_INCLUDE_DIRS) 27 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioCore.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_CORE gnuradio-core) 3 | 4 | FIND_PATH( 5 | GNURADIO_CORE_INCLUDE_DIRS 6 | NAMES gr_core_api.h 7 | HINTS $ENV{GNURADIO_CORE_DIR}/include/gnuradio 8 | ${PC_GNURADIO_CORE_INCLUDEDIR} 9 | ${CMAKE_INSTALL_PREFIX}/include/gnuradio 10 | PATHS /usr/local/include/gnuradio 11 | /usr/include/gnuradio 12 | ) 13 | 14 | FIND_LIBRARY( 15 | GNURADIO_CORE_LIBRARIES 16 | NAMES gnuradio-core 17 | HINTS $ENV{GNURADIO_CORE_DIR}/lib 18 | ${PC_GNURADIO_CORE_LIBDIR} 19 | ${CMAKE_INSTALL_PREFIX}/lib64 20 | ${CMAKE_INSTALL_PREFIX}/lib 21 | PATHS /usr/local/lib 22 | /usr/local/lib64 23 | /usr/lib 24 | /usr/lib64 25 | ) 26 | 27 | INCLUDE(FindPackageHandleStandardArgs) 28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_CORE DEFAULT_MSG GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS) 29 | MARK_AS_ADVANCED(GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS) 30 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioFCD.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_FCD gnuradio-fcd) 3 | 4 | FIND_PATH( 5 | GNURADIO_FCD_INCLUDE_DIRS 6 | NAMES gnuradio/fcd_api.h 7 | HINTS $ENV{GNURADIO_FCD_DIR}/include 8 | ${PC_GNURADIO_FCD_INCLUDEDIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GNURADIO_FCD_LIBRARIES 15 | NAMES gnuradio-fcd 16 | HINTS $ENV{GNURADIO_FCD_DIR}/lib 17 | ${PC_GNURADIO_FCD_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/local/lib64 20 | /usr/lib 21 | /usr/lib64 22 | ) 23 | 24 | if(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES) 25 | set(GNURADIO_FCD_FOUND TRUE CACHE INTERNAL "gnuradio-fcd found") 26 | message(STATUS "Found gnuradio-fcd: ${GNURADIO_FCD_INCLUDE_DIRS}, ${GNURADIO_FCD_LIBRARIES}") 27 | else(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES) 28 | set(GNURADIO_FCD_FOUND FALSE CACHE INTERNAL "gnuradio-fcd found") 29 | message(STATUS "gnuradio-fcd not found.") 30 | endif(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES) 31 | 32 | INCLUDE(FindPackageHandleStandardArgs) 33 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_FCD DEFAULT_MSG GNURADIO_FCD_LIBRARIES GNURADIO_FCD_INCLUDE_DIRS) 34 | MARK_AS_ADVANCED(GNURADIO_FCD_LIBRARIES GNURADIO_FCD_INCLUDE_DIRS) 35 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioFCDPP.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_FCDPP gnuradio-fcdproplus) 3 | 4 | FIND_PATH( 5 | GNURADIO_FCDPP_INCLUDE_DIRS 6 | NAMES fcdproplus/api.h 7 | HINTS $ENV{GNURADIO_FCDPP_DIR}/include 8 | ${PC_GNURADIO_FCDPP_INCLUDEDIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GNURADIO_FCDPP_LIBRARIES 15 | NAMES gnuradio-fcdproplus 16 | HINTS $ENV{GNURADIO_FCDPP_DIR}/lib 17 | ${PC_GNURADIO_FCDPP_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/local/lib64 20 | /usr/lib 21 | /usr/lib64 22 | ) 23 | 24 | if(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES) 25 | set(GNURADIO_FCDPP_FOUND TRUE CACHE INTERNAL "gnuradio-fcdproplus found") 26 | message(STATUS "Found gnuradio-fcdproplus: ${GNURADIO_FCDPP_INCLUDE_DIRS}, ${GNURADIO_FCDPP_LIBRARIES}") 27 | else(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES) 28 | set(GNURADIO_FCDPP_FOUND FALSE CACHE INTERNAL "gnuradio-fcdproplus found") 29 | message(STATUS "gnuradio-fcdproplus not found.") 30 | endif(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES) 31 | 32 | INCLUDE(FindPackageHandleStandardArgs) 33 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_FCDPP DEFAULT_MSG GNURADIO_FCDPP_LIBRARIES GNURADIO_FCDPP_INCLUDE_DIRS) 34 | MARK_AS_ADVANCED(GNURADIO_FCDPP_LIBRARIES GNURADIO_FCDPP_INCLUDE_DIRS) 35 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioIQBalance.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_IQBALANCE gnuradio-iqbalance) 3 | 4 | FIND_PATH( 5 | GNURADIO_IQBALANCE_INCLUDE_DIRS 6 | NAMES iqbalance_api.h 7 | HINTS $ENV{GNURADIO_IQBALANCE_DIR}/include/iqbalance 8 | ${PC_GNURADIO_IQBALANCE_INCLUDEDIR} 9 | ${CMAKE_INSTALL_PREFIX}/include/iqbalance 10 | PATHS /usr/local/include/iqbalance 11 | /usr/include/iqbalance 12 | ) 13 | 14 | FIND_LIBRARY( 15 | GNURADIO_IQBALANCE_LIBRARIES 16 | NAMES gnuradio-iqbalance 17 | HINTS $ENV{GNURADIO_IQBALANCE_DIR}/lib 18 | ${PC_GNURADIO_IQBALANCE_LIBDIR} 19 | ${CMAKE_INSTALL_PREFIX}/lib64 20 | ${CMAKE_INSTALL_PREFIX}/lib 21 | PATHS /usr/local/lib 22 | /usr/local/lib64 23 | /usr/lib 24 | /usr/lib64 25 | ) 26 | 27 | INCLUDE(FindPackageHandleStandardArgs) 28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_IQBALANCE DEFAULT_MSG GNURADIO_IQBALANCE_LIBRARIES GNURADIO_IQBALANCE_INCLUDE_DIRS) 29 | MARK_AS_ADVANCED(GNURADIO_IQBALANCE_LIBRARIES GNURADIO_IQBALANCE_INCLUDE_DIRS) 30 | -------------------------------------------------------------------------------- /cmake/Modules/FindGnuradioUHD.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GNURADIO_UHD gnuradio-uhd) 3 | 4 | FIND_PATH( 5 | GNURADIO_UHD_INCLUDE_DIRS 6 | NAMES gnuradio/gr_uhd_api.h 7 | HINTS $ENV{GNURADIO_UHD_DIR}/include 8 | ${PC_GNURADIO_UHD_INCLUDEDIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | GNURADIO_UHD_LIBRARIES 15 | NAMES gnuradio-uhd 16 | HINTS $ENV{GNURADIO_UHD_DIR}/lib 17 | ${PC_GNURADIO_UHD_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/local/lib64 20 | /usr/lib 21 | /usr/lib64 22 | ) 23 | 24 | if(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES) 25 | set(GNURADIO_UHD_FOUND TRUE CACHE INTERNAL "gnuradio-uhd found") 26 | message(STATUS "Found gnuradio-uhd: ${GNURADIO_UHD_INCLUDE_DIRS}, ${GNURADIO_UHD_LIBRARIES}") 27 | else(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES) 28 | set(GNURADIO_UHD_FOUND FALSE CACHE INTERNAL "gnuradio-uhd found") 29 | message(STATUS "gnuradio-uhd not found.") 30 | endif(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES) 31 | 32 | INCLUDE(FindPackageHandleStandardArgs) 33 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_UHD DEFAULT_MSG GNURADIO_UHD_LIBRARIES GNURADIO_UHD_INCLUDE_DIRS) 34 | MARK_AS_ADVANCED(GNURADIO_UHD_LIBRARIES GNURADIO_UHD_INCLUDE_DIRS) 35 | -------------------------------------------------------------------------------- /cmake/Modules/FindGruel.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_GRUEL gruel) 3 | 4 | FIND_PATH( 5 | GRUEL_INCLUDE_DIRS 6 | NAMES gruel/attributes.h 7 | HINTS $ENV{GRUEL_DIR}/include 8 | ${PC_GRUEL_INCLUDEDIR} 9 | ${CMAKE_INSTALL_PREFIX}/include 10 | PATHS /usr/local/include 11 | /usr/include 12 | ) 13 | 14 | FIND_LIBRARY( 15 | GRUEL_LIBRARIES 16 | NAMES gruel 17 | HINTS $ENV{GRUEL_DIR}/lib 18 | ${PC_GRUEL_LIBDIR} 19 | ${CMAKE_INSTALL_PREFIX}/lib 20 | ${CMAKE_INSTALL_PREFIX}/lib64 21 | PATHS /usr/local/lib 22 | /usr/local/lib64 23 | /usr/lib 24 | /usr/lib64 25 | ) 26 | 27 | INCLUDE(FindPackageHandleStandardArgs) 28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GRUEL DEFAULT_MSG GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS) 29 | MARK_AS_ADVANCED(GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS) 30 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibDSD.cmake: -------------------------------------------------------------------------------- 1 | if(NOT LIBDSD_FOUND) 2 | pkg_check_modules (LIBDSD_PKG libdsd) 3 | find_path(LIBDSD_INCLUDE_DIR NAMES dsd_api.h 4 | PATHS 5 | ${LIBDSD_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | /usr/local/include/dsd 9 | ) 10 | 11 | find_library(LIBDSD_LIBRARIES NAMES gr-dsd 12 | PATHS 13 | ${LIBDSD_PKG_LIBRARY_DIRS} 14 | /usr/lib 15 | /usr/local/lib 16 | ) 17 | 18 | if(LIBDSD_INCLUDE_DIR AND LIBDSD_LIBRARIES) 19 | set(LIBDSD_FOUND TRUE CACHE INTERNAL "libdsd found") 20 | message(STATUS "Found libdsd: ${LIBDSD_INCLUDE_DIR}, ${LIBDSD_LIBRARIES}") 21 | else(LIB_INCLUDE_DIR AND LIBDSD_LIBRARIES) 22 | set(LIBDSD_FOUND FALSE CACHE INTERNAL "libdsd found") 23 | message(STATUS "libdsd not found.") 24 | endif(LIBDSD_INCLUDE_DIR AND LIBDSD_LIBRARIES) 25 | 26 | mark_as_advanced(LIBDSD_INCLUDE_DIR LIBDSD_LIBRARIES) 27 | 28 | endif(NOT LIBDSD_FOUND) 29 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibDSD.cmake~: -------------------------------------------------------------------------------- 1 | if(NOT LIBDSD_FOUND) 2 | pkg_check_modules (LIBDSD_PKG libdsd) 3 | find_path(LIBDSD_INCLUDE_DIR NAMES dsd_api.h 4 | PATHS 5 | ${LIBDSD_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | /usr/local/include/dsd 9 | ) 10 | 11 | find_library(LIBDSD_LIBRARIES NAMES libgr-dsd 12 | PATHS 13 | ${LIBDSD_PKG_LIBRARY_DIRS} 14 | /usr/lib 15 | /usr/local/lib 16 | ) 17 | 18 | if(LIBDSD_INCLUDE_DIR AND LIBDSD_LIBRARIES) 19 | set(LIBDSD_FOUND TRUE CACHE INTERNAL "libdsd found") 20 | message(STATUS "Found libdsd: ${LIBDSD_INCLUDE_DIR}, ${LIBDSD_LIBRARIES}") 21 | else(LIB_INCLUDE_DIR AND LIBDSD_LIBRARIES) 22 | set(LIBDSD_FOUND FALSE CACHE INTERNAL "libdsd found") 23 | message(STATUS "libdsd not found.") 24 | endif(LIBDSD_INCLUDE_DIR AND LIBDSD_LIBRARIES) 25 | 26 | mark_as_advanced(LIBDSD_INCLUDE_DIR LIBDSD_LIBRARIES) 27 | 28 | endif(NOT LIBDSD_FOUND) 29 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibHackRF.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_LIBHACKRF libhackrf) 3 | 4 | FIND_PATH( 5 | LIBHACKRF_INCLUDE_DIRS 6 | NAMES libhackrf/hackrf.h 7 | HINTS $ENV{LIBHACKRF_DIR}/include 8 | ${PC_LIBHACKRF_INCLUDEDIR} 9 | PATHS /usr/local/include 10 | /usr/include 11 | ) 12 | 13 | FIND_LIBRARY( 14 | LIBHACKRF_LIBRARIES 15 | NAMES hackrf 16 | HINTS $ENV{LIBHACKRF_DIR}/lib 17 | ${PC_LIBHACKRF_LIBDIR} 18 | PATHS /usr/local/lib 19 | /usr/lib 20 | ) 21 | 22 | INCLUDE(FindPackageHandleStandardArgs) 23 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBHACKRF DEFAULT_MSG LIBHACKRF_LIBRARIES LIBHACKRF_INCLUDE_DIRS) 24 | MARK_AS_ADVANCED(LIBHACKRF_LIBRARIES LIBHACKRF_INCLUDE_DIRS) 25 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibMiriSDR.cmake: -------------------------------------------------------------------------------- 1 | if(NOT LIBMIRISDR_FOUND) 2 | pkg_check_modules (LIBMIRISDR_PKG libmirisdr) 3 | find_path(LIBMIRISDR_INCLUDE_DIR NAMES mirisdr.h 4 | PATHS 5 | ${LIBMIRISDR_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | ) 9 | 10 | find_library(LIBMIRISDR_LIBRARIES NAMES mirisdr 11 | PATHS 12 | ${LIBMIRISDR_PKG_LIBRARY_DIRS} 13 | /usr/lib 14 | /usr/local/lib 15 | ) 16 | 17 | if(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES) 18 | set(LIBMIRISDR_FOUND TRUE CACHE INTERNAL "libmirisdr found") 19 | message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIR}, ${LIBMIRISDR_LIBRARIES}") 20 | else(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES) 21 | set(LIBMIRISDR_FOUND FALSE CACHE INTERNAL "libmirisdr found") 22 | message(STATUS "libmirisdr not found.") 23 | endif(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES) 24 | 25 | mark_as_advanced(LIBMIRISDR_INCLUDE_DIR LIBMIRISDR_LIBRARIES) 26 | 27 | endif(NOT LIBMIRISDR_FOUND) 28 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibOsmoSDR.cmake: -------------------------------------------------------------------------------- 1 | if(NOT LIBOSMOSDR_FOUND) 2 | pkg_check_modules (LIBOSMOSDR_PKG libosmosdr) 3 | find_path(LIBOSMOSDR_INCLUDE_DIR NAMES osmosdr_api.h 4 | PATHS 5 | ${LIBOSMOSDR_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | /usr/local/include/osmosdr 9 | ) 10 | 11 | find_library(LIBOSMOSDR_LIBRARIES NAMES gnuradio-osmosdr 12 | PATHS 13 | ${LIBOSMOSDR_PKG_LIBRARY_DIRS} 14 | /usr/lib 15 | /usr/local/lib 16 | ) 17 | 18 | if(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 19 | set(LIBOSMOSDR_FOUND TRUE CACHE INTERNAL "libosmosdr found") 20 | message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIR}, ${LIBOSMOSDR_LIBRARIES}") 21 | else(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 22 | set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr found") 23 | message(STATUS "libosmosdr not found.") 24 | endif(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 25 | 26 | mark_as_advanced(LIBOSMOSDR_INCLUDE_DIR LIBOSMOSDR_LIBRARIES) 27 | 28 | endif(NOT LIBOSMOSDR_FOUND) 29 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibOsmoSDR.cmake~: -------------------------------------------------------------------------------- 1 | if(NOT LIBOSMOSDR_FOUND) 2 | pkg_check_modules (LIBOSMOSDR_PKG libosmosdr) 3 | find_path(LIBOSMOSDR_INCLUDE_DIR NAMES osmosdr.h 4 | PATHS 5 | ${LIBOSMOSDR_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | ) 9 | 10 | find_library(LIBOSMOSDR_LIBRARIES NAMES osmosdr 11 | PATHS 12 | ${LIBOSMOSDR_PKG_LIBRARY_DIRS} 13 | /usr/lib 14 | /usr/local/lib 15 | ) 16 | 17 | if(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 18 | set(LIBOSMOSDR_FOUND TRUE CACHE INTERNAL "libosmosdr found") 19 | message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIR}, ${LIBOSMOSDR_LIBRARIES}") 20 | else(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 21 | set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr found") 22 | message(STATUS "libosmosdr not found.") 23 | endif(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES) 24 | 25 | mark_as_advanced(LIBOSMOSDR_INCLUDE_DIR LIBOSMOSDR_LIBRARIES) 26 | 27 | endif(NOT LIBOSMOSDR_FOUND) 28 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibRTLSDR.cmake: -------------------------------------------------------------------------------- 1 | if(NOT LIBRTLSDR_FOUND) 2 | pkg_check_modules (LIBRTLSDR_PKG librtlsdr) 3 | find_path(LIBRTLSDR_INCLUDE_DIR NAMES rtl-sdr.h 4 | PATHS 5 | ${LIBRTLSDR_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | ) 9 | 10 | find_library(LIBRTLSDR_LIBRARIES NAMES rtlsdr 11 | PATHS 12 | ${LIBRTLSDR_PKG_LIBRARY_DIRS} 13 | /usr/lib 14 | /usr/local/lib 15 | ) 16 | 17 | if(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES) 18 | set(LIBRTLSDR_FOUND TRUE CACHE INTERNAL "librtlsdr found") 19 | message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIR}, ${LIBRTLSDR_LIBRARIES}") 20 | else(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES) 21 | set(LIBRTLSDR_FOUND FALSE CACHE INTERNAL "librtlsdr found") 22 | message(STATUS "librtlsdr not found.") 23 | endif(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES) 24 | 25 | mark_as_advanced(LIBRTLSDR_INCLUDE_DIR LIBRTLSDR_LIBRARIES) 26 | 27 | endif(NOT LIBRTLSDR_FOUND) 28 | -------------------------------------------------------------------------------- /cmake/Modules/FindLibbladeRF.cmake: -------------------------------------------------------------------------------- 1 | if(NOT LIBBLADERF_FOUND) 2 | pkg_check_modules (LIBBLADERF_PKG libbladeRF) 3 | find_path(LIBBLADERF_INCLUDE_DIR NAMES libbladeRF.h 4 | PATHS 5 | ${LIBBLADERF_PKG_INCLUDE_DIRS} 6 | /usr/include 7 | /usr/local/include 8 | ) 9 | 10 | find_library(LIBBLADERF_LIBRARIES NAMES bladeRF 11 | PATHS 12 | ${LIBBLADERF_PKG_LIBRARY_DIRS} 13 | /usr/lib 14 | /usr/local/lib 15 | ) 16 | 17 | if(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES) 18 | set(LIBBLADERF_FOUND TRUE CACHE INTERNAL "libbladeRF found") 19 | message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIR}, ${LIBBLADERF_LIBRARIES}") 20 | else(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES) 21 | set(LIBBLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF found") 22 | message(STATUS "libbladeRF not found.") 23 | endif(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES) 24 | 25 | mark_as_advanced(LIBBLADERF_INCLUDE_DIR LIBBLADERF_LIBRARIES) 26 | 27 | endif(NOT LIBBLADERF_FOUND) 28 | -------------------------------------------------------------------------------- /cmake/Modules/FindUHD.cmake: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # Find the library for the USRP Hardware Driver 3 | ######################################################################## 4 | 5 | INCLUDE(FindPkgConfig) 6 | PKG_CHECK_MODULES(PC_UHD uhd) 7 | 8 | FIND_PATH( 9 | UHD_INCLUDE_DIRS 10 | NAMES uhd/config.hpp 11 | HINTS $ENV{UHD_DIR}/include 12 | ${PC_UHD_INCLUDEDIR} 13 | PATHS /usr/local/include 14 | /usr/include 15 | ) 16 | 17 | FIND_LIBRARY( 18 | UHD_LIBRARIES 19 | NAMES uhd 20 | HINTS $ENV{UHD_DIR}/lib 21 | ${PC_UHD_LIBDIR} 22 | PATHS /usr/local/lib 23 | /usr/lib 24 | ) 25 | 26 | INCLUDE(FindPackageHandleStandardArgs) 27 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(UHD DEFAULT_MSG UHD_LIBRARIES UHD_INCLUDE_DIRS) 28 | MARK_AS_ADVANCED(UHD_LIBRARIES UHD_INCLUDE_DIRS) 29 | -------------------------------------------------------------------------------- /cmake/Modules/GrComponent.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_COMPONENT_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_COMPONENT_CMAKE TRUE) 24 | 25 | set(_gr_enabled_components "" CACHE INTERNAL "" FORCE) 26 | set(_gr_disabled_components "" CACHE INTERNAL "" FORCE) 27 | 28 | if(NOT DEFINED ENABLE_DEFAULT) 29 | set(ENABLE_DEFAULT ON) 30 | message(STATUS "") 31 | message(STATUS "The build system will automatically enable all components.") 32 | message(STATUS "Use -DENABLE_DEFAULT=OFF to disable components by default.") 33 | endif() 34 | 35 | ######################################################################## 36 | # Register a component into the system 37 | # - name: canonical component name 38 | # - var: variable for enabled status 39 | # - argn: list of dependencies 40 | ######################################################################## 41 | function(GR_REGISTER_COMPONENT name var) 42 | include(CMakeDependentOption) 43 | message(STATUS "") 44 | message(STATUS "Configuring ${name} support...") 45 | foreach(dep ${ARGN}) 46 | message(STATUS " Dependency ${dep} = ${${dep}}") 47 | endforeach(dep) 48 | 49 | #if the user set the var to force, we note this 50 | if("${${var}}" STREQUAL "FORCE") 51 | set(${var} ON) 52 | set(var_force TRUE) 53 | else() 54 | set(var_force FALSE) 55 | endif() 56 | 57 | #rewrite the dependency list so that deps that are also components use the cached version 58 | unset(comp_deps) 59 | foreach(dep ${ARGN}) 60 | list(FIND _gr_enabled_components ${dep} dep_enb_index) 61 | list(FIND _gr_disabled_components ${dep} dep_dis_index) 62 | if (${dep_enb_index} EQUAL -1 AND ${dep_dis_index} EQUAL -1) 63 | list(APPEND comp_deps ${dep}) 64 | else() 65 | list(APPEND comp_deps ${dep}_cached) #is a component, use cached version 66 | endif() 67 | endforeach(dep) 68 | 69 | #setup the dependent option for this component 70 | CMAKE_DEPENDENT_OPTION(${var} "enable ${name} support" ${ENABLE_DEFAULT} "${comp_deps}" OFF) 71 | set(${var} "${${var}}" PARENT_SCOPE) 72 | set(${var}_cached "${${var}}" CACHE INTERNAL "" FORCE) 73 | 74 | #force was specified, but the dependencies were not met 75 | if(NOT ${var} AND var_force) 76 | message(FATAL_ERROR "user force-enabled ${name} but configuration checked failed") 77 | endif() 78 | 79 | #append the component into one of the lists 80 | if(${var}) 81 | message(STATUS " Enabling ${name} support.") 82 | list(APPEND _gr_enabled_components ${name}) 83 | else(${var}) 84 | message(STATUS " Disabling ${name} support.") 85 | list(APPEND _gr_disabled_components ${name}) 86 | endif(${var}) 87 | message(STATUS " Override with -D${var}=ON/OFF") 88 | 89 | #make components lists into global variables 90 | set(_gr_enabled_components ${_gr_enabled_components} CACHE INTERNAL "" FORCE) 91 | set(_gr_disabled_components ${_gr_disabled_components} CACHE INTERNAL "" FORCE) 92 | endfunction(GR_REGISTER_COMPONENT) 93 | 94 | ######################################################################## 95 | # Print the registered component summary 96 | ######################################################################## 97 | function(GR_PRINT_COMPONENT_SUMMARY) 98 | message(STATUS "") 99 | message(STATUS "######################################################") 100 | message(STATUS "# gr-osmosdr enabled components ") 101 | message(STATUS "######################################################") 102 | foreach(comp ${_gr_enabled_components}) 103 | message(STATUS " * ${comp}") 104 | endforeach(comp) 105 | 106 | message(STATUS "") 107 | message(STATUS "######################################################") 108 | message(STATUS "# gr-osmosdr disabled components ") 109 | message(STATUS "######################################################") 110 | foreach(comp ${_gr_disabled_components}) 111 | message(STATUS " * ${comp}") 112 | endforeach(comp) 113 | 114 | message(STATUS "") 115 | endfunction(GR_PRINT_COMPONENT_SUMMARY) 116 | -------------------------------------------------------------------------------- /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 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 | 212 | ######################################################################## 213 | # Control use of gr_logger 214 | # Usage: 215 | # GR_LOGGING() 216 | # 217 | # Will set ENABLE_GR_LOG to 1 by default. 218 | # Can manually set with -DENABLE_GR_LOG=0|1 219 | ######################################################################## 220 | function(GR_LOGGING) 221 | find_package(Log4cpp) 222 | 223 | OPTION(ENABLE_GR_LOG "Use gr_logger" ON) 224 | if(ENABLE_GR_LOG) 225 | # If gr_logger is enabled, make it usable 226 | add_definitions( -DENABLE_GR_LOG ) 227 | 228 | # also test LOG4CPP; if we have it, use this version of the logger 229 | # otherwise, default to the stdout/stderr model. 230 | if(LOG4CPP_FOUND) 231 | SET(HAVE_LOG4CPP True CACHE INTERNAL "" FORCE) 232 | add_definitions( -DHAVE_LOG4CPP ) 233 | else(not LOG4CPP_FOUND) 234 | SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) 235 | SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) 236 | SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) 237 | SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) 238 | endif(LOG4CPP_FOUND) 239 | 240 | SET(ENABLE_GR_LOG ${ENABLE_GR_LOG} CACHE INTERNAL "" FORCE) 241 | 242 | else(ENABLE_GR_LOG) 243 | SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) 244 | SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) 245 | SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) 246 | SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) 247 | endif(ENABLE_GR_LOG) 248 | 249 | message(STATUS "ENABLE_GR_LOG set to ${ENABLE_GR_LOG}.") 250 | message(STATUS "HAVE_LOG4CPP set to ${HAVE_LOG4CPP}.") 251 | message(STATUS "LOG4CPP_LIBRARIES set to ${LOG4CPP_LIBRARIES}.") 252 | 253 | endfunction(GR_LOGGING) 254 | 255 | ######################################################################## 256 | # Run GRCC to compile .grc files into .py files. 257 | # 258 | # Usage: GRCC(filename, directory) 259 | # - filenames: List of file name of .grc file 260 | # - directory: directory of built .py file - usually in 261 | # ${CMAKE_CURRENT_BINARY_DIR} 262 | # - Sets PYFILES: output converted GRC file names to Python files. 263 | ######################################################################## 264 | function(GRCC) 265 | # Extract directory from list of args, remove it for the list of filenames. 266 | list(GET ARGV -1 directory) 267 | list(REMOVE_AT ARGV -1) 268 | set(filenames ${ARGV}) 269 | file(MAKE_DIRECTORY ${directory}) 270 | 271 | SET(GRCC_COMMAND ${CMAKE_SOURCE_DIR}/gr-utils/src/python/grcc) 272 | 273 | # GRCC uses some stuff in grc and gnuradio-core, so we force 274 | # the known paths here 275 | list(APPEND PYTHONPATHS 276 | ${CMAKE_SOURCE_DIR} 277 | ${CMAKE_SOURCE_DIR}/gnuradio-core/src/python 278 | ${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/swig 279 | ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig 280 | ) 281 | 282 | if(WIN32) 283 | #SWIG generates the python library files into a subdirectory. 284 | #Therefore, we must append this subdirectory into PYTHONPATH. 285 | #Only do this for the python directories matching the following: 286 | foreach(pydir ${PYTHONPATHS}) 287 | get_filename_component(name ${pydir} NAME) 288 | if(name MATCHES "^(swig|lib|src)$") 289 | list(APPEND PYTHONPATHS ${pydir}/${CMAKE_BUILD_TYPE}) 290 | endif() 291 | endforeach(pydir) 292 | endif(WIN32) 293 | 294 | file(TO_NATIVE_PATH "${PYTHONPATHS}" pypath) 295 | 296 | if(UNIX) 297 | list(APPEND pypath "$PYTHONPATH") 298 | string(REPLACE ";" ":" pypath "${pypath}") 299 | set(ENV{PYTHONPATH} ${pypath}) 300 | endif(UNIX) 301 | 302 | if(WIN32) 303 | list(APPEND pypath "%PYTHONPATH%") 304 | string(REPLACE ";" "\\;" pypath "${pypath}") 305 | #list(APPEND environs "PYTHONPATH=${pypath}") 306 | set(ENV{PYTHONPATH} ${pypath}) 307 | endif(WIN32) 308 | 309 | foreach(f ${filenames}) 310 | execute_process( 311 | COMMAND ${GRCC_COMMAND} -d ${directory} ${f} 312 | ) 313 | string(REPLACE ".grc" ".py" pyfile "${f}") 314 | string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" pyfile "${pyfile}") 315 | list(APPEND pyfiles ${pyfile}) 316 | endforeach(f) 317 | 318 | set(PYFILES ${pyfiles} PARENT_SCOPE) 319 | endfunction(GRCC) 320 | -------------------------------------------------------------------------------- /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 | if(LINUX AND EXISTS "/etc/slackware-version") 41 | set(SLACKWARE TRUE) 42 | endif() 43 | 44 | ######################################################################## 45 | # when the library suffix should be 64 (applies to redhat linux family) 46 | ######################################################################## 47 | if (REDHAT OR SLACKWARE) 48 | set(LIB64_CONVENTION TRUE) 49 | endif() 50 | 51 | if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") 52 | set(LIB_SUFFIX 64) 53 | endif() 54 | set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix") 55 | -------------------------------------------------------------------------------- /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 2) 40 | 41 | #and if that fails use the find program routine 42 | if(NOT PYTHONINTERP_FOUND) 43 | find_program(PYTHON_EXECUTABLE NAMES python python2 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: 80 | import ${mod} 81 | assert ${cmd} 82 | except ImportError, AssertionError: exit(-1) 83 | except: pass 84 | #########################################" 85 | RESULT_VARIABLE ${have} 86 | ) 87 | if(${have} EQUAL 0) 88 | message(STATUS "Python checking for ${desc} - found") 89 | set(${have} TRUE) 90 | else(${have} EQUAL 0) 91 | message(STATUS "Python checking for ${desc} - not found") 92 | set(${have} FALSE) 93 | endif(${have} EQUAL 0) 94 | endmacro(GR_PYTHON_CHECK_MODULE) 95 | 96 | ######################################################################## 97 | # Sets the python installation directory GR_PYTHON_DIR 98 | ######################################################################## 99 | if(NOT DEFINED GR_PYTHON_DIR) 100 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " 101 | from distutils import sysconfig 102 | print sysconfig.get_python_lib(plat_specific=True, prefix='') 103 | " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE 104 | ) 105 | endif() 106 | file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) 107 | 108 | ######################################################################## 109 | # Create an always-built target with a unique name 110 | # Usage: GR_UNIQUE_TARGET( ) 111 | ######################################################################## 112 | function(GR_UNIQUE_TARGET desc) 113 | file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) 114 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib 115 | unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] 116 | print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" 117 | OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) 118 | add_custom_target(${_target} ALL DEPENDS ${ARGN}) 119 | endfunction(GR_UNIQUE_TARGET) 120 | 121 | ######################################################################## 122 | # Install python sources (also builds and installs byte-compiled python) 123 | ######################################################################## 124 | function(GR_PYTHON_INSTALL) 125 | include(CMakeParseArgumentsCopy) 126 | CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) 127 | 128 | #################################################################### 129 | if(GR_PYTHON_INSTALL_FILES) 130 | #################################################################### 131 | install(${ARGN}) #installs regular python files 132 | 133 | #create a list of all generated files 134 | unset(pysrcfiles) 135 | unset(pycfiles) 136 | unset(pyofiles) 137 | foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) 138 | get_filename_component(pyfile ${pyfile} ABSOLUTE) 139 | list(APPEND pysrcfiles ${pyfile}) 140 | 141 | #determine if this file is in the source or binary directory 142 | file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) 143 | string(LENGTH "${source_rel_path}" source_rel_path_len) 144 | file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) 145 | string(LENGTH "${binary_rel_path}" binary_rel_path_len) 146 | 147 | #and set the generated path appropriately 148 | if(${source_rel_path_len} GREATER ${binary_rel_path_len}) 149 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) 150 | else() 151 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) 152 | endif() 153 | list(APPEND pycfiles ${pygenfile}c) 154 | list(APPEND pyofiles ${pygenfile}o) 155 | 156 | #ensure generation path exists 157 | get_filename_component(pygen_path ${pygenfile} PATH) 158 | file(MAKE_DIRECTORY ${pygen_path}) 159 | 160 | endforeach(pyfile) 161 | 162 | #the command to generate the pyc files 163 | add_custom_command( 164 | DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} 165 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} 166 | ) 167 | 168 | #the command to generate the pyo files 169 | add_custom_command( 170 | DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} 171 | COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} 172 | ) 173 | 174 | #create install rule and add generated files to target list 175 | set(python_install_gen_targets ${pycfiles} ${pyofiles}) 176 | install(FILES ${python_install_gen_targets} 177 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} 178 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} 179 | ) 180 | 181 | 182 | #################################################################### 183 | elseif(GR_PYTHON_INSTALL_PROGRAMS) 184 | #################################################################### 185 | file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) 186 | 187 | if (CMAKE_CROSSCOMPILING) 188 | set(pyexe_native /usr/bin/env python) 189 | endif() 190 | 191 | foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) 192 | get_filename_component(pyfile_name ${pyfile} NAME) 193 | get_filename_component(pyfile ${pyfile} ABSOLUTE) 194 | string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") 195 | list(APPEND python_install_gen_targets ${pyexefile}) 196 | 197 | get_filename_component(pyexefile_path ${pyexefile} PATH) 198 | file(MAKE_DIRECTORY ${pyexefile_path}) 199 | 200 | add_custom_command( 201 | OUTPUT ${pyexefile} DEPENDS ${pyfile} 202 | COMMAND ${PYTHON_EXECUTABLE} -c 203 | \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" 204 | COMMENT "Shebangin ${pyfile_name}" 205 | ) 206 | 207 | #on windows, python files need an extension to execute 208 | get_filename_component(pyfile_ext ${pyfile} EXT) 209 | if(WIN32 AND NOT pyfile_ext) 210 | set(pyfile_name "${pyfile_name}.py") 211 | endif() 212 | 213 | install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} 214 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} 215 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} 216 | ) 217 | endforeach(pyfile) 218 | 219 | endif() 220 | 221 | GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) 222 | 223 | endfunction(GR_PYTHON_INSTALL) 224 | 225 | ######################################################################## 226 | # Write the python helper script that generates byte code files 227 | ######################################################################## 228 | file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " 229 | import sys, py_compile 230 | files = sys.argv[1:] 231 | srcs, gens = files[:len(files)/2], files[len(files)/2:] 232 | for src, gen in zip(srcs, gens): 233 | py_compile.compile(file=src, cfile=gen, doraise=True) 234 | ") 235 | -------------------------------------------------------------------------------- /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 | if(ENABLE_DOXYGEN) 37 | 38 | #setup the input files variable list, quote formated 39 | set(input_files) 40 | unset(INPUT_PATHS) 41 | foreach(input_path ${ARGN}) 42 | if (IS_DIRECTORY ${input_path}) #when input path is a directory 43 | file(GLOB input_path_h_files ${input_path}/*.h) 44 | else() #otherwise its just a file, no glob 45 | set(input_path_h_files ${input_path}) 46 | endif() 47 | list(APPEND input_files ${input_path_h_files}) 48 | set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"") 49 | endforeach(input_path) 50 | 51 | #determine the output directory 52 | get_filename_component(name ${output_file} NAME_WE) 53 | get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH) 54 | set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs) 55 | make_directory(${OUTPUT_DIRECTORY}) 56 | 57 | #generate the Doxyfile used by doxygen 58 | configure_file( 59 | ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in 60 | ${OUTPUT_DIRECTORY}/Doxyfile 61 | @ONLY) 62 | 63 | #Create a dummy custom command that depends on other targets 64 | include(GrMiscUtils) 65 | GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS}) 66 | 67 | #call doxygen on the Doxyfile + input headers 68 | add_custom_command( 69 | OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml 70 | DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps} 71 | COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile 72 | COMMENT "Generating doxygen xml for ${name} docs" 73 | ) 74 | 75 | #call the swig_doc script on the xml files 76 | add_custom_command( 77 | OUTPUT ${output_file} 78 | DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml 79 | COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} 80 | ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py 81 | ${OUTPUT_DIRECTORY}/xml 82 | ${output_file} 83 | COMMENT "Generating python docstrings for ${name}" 84 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen 85 | ) 86 | 87 | else(ENABLE_DOXYGEN) 88 | file(WRITE ${output_file} "\n") #no doxygen -> empty file 89 | endif(ENABLE_DOXYGEN) 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_TARGET_DEPS ${GR_SWIG_TARGET_DEPS}) 112 | GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) 113 | add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE}) 114 | list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc) 115 | endif() 116 | 117 | #append additional include directories 118 | find_package(PythonLibs 2) 119 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) 120 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) 121 | list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) 122 | list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) 123 | 124 | #determine include dependencies for swig file 125 | execute_process( 126 | COMMAND ${PYTHON_EXECUTABLE} 127 | ${CMAKE_BINARY_DIR}/get_swig_deps.py 128 | "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" 129 | OUTPUT_STRIP_TRAILING_WHITESPACE 130 | OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS 131 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 132 | ) 133 | 134 | #Create a dummy custom command that depends on other targets 135 | include(GrMiscUtils) 136 | GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS}) 137 | set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag) 138 | add_custom_command( 139 | OUTPUT ${tag_file} 140 | DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps} 141 | COMMAND ${CMAKE_COMMAND} -E touch ${tag_file} 142 | ) 143 | 144 | #append the specified include directories 145 | include_directories(${GR_SWIG_INCLUDE_DIRS}) 146 | list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) 147 | 148 | #setup the swig flags with flags and include directories 149 | set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS}) 150 | foreach(dir ${GR_SWIG_INCLUDE_DIRS}) 151 | list(APPEND CMAKE_SWIG_FLAGS "-I${dir}") 152 | endforeach(dir) 153 | 154 | #set the C++ property on the swig .i file so it builds 155 | set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON) 156 | 157 | #setup the actual swig library target to be built 158 | include(UseSWIG) 159 | SWIG_ADD_MODULE(${name} python ${ifiles}) 160 | SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES}) 161 | 162 | endmacro(GR_SWIG_MAKE) 163 | 164 | ######################################################################## 165 | # Install swig targets generated by GR_SWIG_MAKE. Usage: 166 | # GR_SWIG_INSTALL( 167 | # TARGETS target target target... 168 | # [DESTINATION destination] 169 | # [COMPONENT component] 170 | # ) 171 | ######################################################################## 172 | macro(GR_SWIG_INSTALL) 173 | 174 | include(CMakeParseArgumentsCopy) 175 | CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN}) 176 | 177 | foreach(name ${GR_SWIG_INSTALL_TARGETS}) 178 | install(TARGETS ${SWIG_MODULE_${name}_REAL_NAME} 179 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 180 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT} 181 | ) 182 | 183 | include(GrPython) 184 | GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py 185 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 186 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT} 187 | ) 188 | 189 | GR_LIBTOOL( 190 | TARGET ${SWIG_MODULE_${name}_REAL_NAME} 191 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION} 192 | ) 193 | 194 | endforeach(name) 195 | 196 | endmacro(GR_SWIG_INSTALL) 197 | 198 | ######################################################################## 199 | # Generate a python file that can determine swig dependencies. 200 | # Used by the make macro above to determine extra dependencies. 201 | # When you build C++, CMake figures out the header dependencies. 202 | # This code essentially performs that logic for swig includes. 203 | ######################################################################## 204 | file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py " 205 | 206 | import os, sys, re 207 | 208 | i_include_matcher = re.compile('%(include|import)\\s*[<|\"](.*)[>|\"]') 209 | h_include_matcher = re.compile('#(include)\\s*[<|\"](.*)[>|\"]') 210 | include_dirs = sys.argv[2].split(';') 211 | 212 | def get_swig_incs(file_path): 213 | if file_path.endswith('.i'): matcher = i_include_matcher 214 | else: matcher = h_include_matcher 215 | file_contents = open(file_path, 'r').read() 216 | return matcher.findall(file_contents, re.MULTILINE) 217 | 218 | def get_swig_deps(file_path, level): 219 | deps = [file_path] 220 | if level == 0: return deps 221 | for keyword, inc_file in get_swig_incs(file_path): 222 | for inc_dir in include_dirs: 223 | inc_path = os.path.join(inc_dir, inc_file) 224 | if not os.path.exists(inc_path): continue 225 | deps.extend(get_swig_deps(inc_path, level-1)) 226 | break #found, we dont search in lower prio inc dirs 227 | return deps 228 | 229 | if __name__ == '__main__': 230 | ifiles = sys.argv[1].split(';') 231 | deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], []) 232 | #sys.stderr.write(';'.join(set(deps)) + '\\n\\n') 233 | print(';'.join(set(deps))) 234 | ") 235 | -------------------------------------------------------------------------------- /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 | #Ensure that the build exe also appears in the PATH. 37 | list(APPEND GR_TEST_TARGET_DEPS ${ARGN}) 38 | 39 | #In the land of windows, all libraries must be in the PATH. 40 | #Since the dependent libraries are not yet installed, 41 | #we must manually set them in the PATH to run tests. 42 | #The following appends the path of a target dependency. 43 | foreach(target ${GR_TEST_TARGET_DEPS}) 44 | get_target_property(location ${target} LOCATION) 45 | if(location) 46 | get_filename_component(path ${location} PATH) 47 | string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path}) 48 | list(APPEND GR_TEST_LIBRARY_DIRS ${path}) 49 | endif(location) 50 | endforeach(target) 51 | 52 | if(WIN32) 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(LD_PATH_VAR "LD_LIBRARY_PATH") 78 | if(APPLE) 79 | set(LD_PATH_VAR "DYLD_LIBRARY_PATH") 80 | endif() 81 | 82 | set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH") 83 | list(APPEND libpath "$${LD_PATH_VAR}") 84 | list(APPEND pypath "$PYTHONPATH") 85 | 86 | #replace list separator with the path separator 87 | string(REPLACE ";" ":" libpath "${libpath}") 88 | string(REPLACE ";" ":" pypath "${pypath}") 89 | list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}") 90 | 91 | #generate a bat file that sets the environment and runs the test 92 | find_program(SHELL sh) 93 | set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh) 94 | file(WRITE ${sh_file} "#!${SHELL}\n") 95 | #each line sets an environment variable 96 | foreach(environ ${environs}) 97 | file(APPEND ${sh_file} "export ${environ}\n") 98 | endforeach(environ) 99 | #load the command to run with its arguments 100 | foreach(arg ${ARGN}) 101 | file(APPEND ${sh_file} "${arg} ") 102 | endforeach(arg) 103 | file(APPEND ${sh_file} "\n") 104 | 105 | #make the shell file executable 106 | execute_process(COMMAND chmod +x ${sh_file}) 107 | 108 | add_test(${test_name} ${SHELL} ${sh_file}) 109 | 110 | endif(UNIX) 111 | 112 | if(WIN32) 113 | list(APPEND libpath ${DLL_PATHS} "%PATH%") 114 | list(APPEND pypath "%PYTHONPATH%") 115 | 116 | #replace list separator with the path separator (escaped) 117 | string(REPLACE ";" "\\;" libpath "${libpath}") 118 | string(REPLACE ";" "\\;" pypath "${pypath}") 119 | list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}") 120 | 121 | #generate a bat file that sets the environment and runs the test 122 | set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat) 123 | file(WRITE ${bat_file} "@echo off\n") 124 | #each line sets an environment variable 125 | foreach(environ ${environs}) 126 | file(APPEND ${bat_file} "SET ${environ}\n") 127 | endforeach(environ) 128 | #load the command to run with its arguments 129 | foreach(arg ${ARGN}) 130 | file(APPEND ${bat_file} "${arg} ") 131 | endforeach(arg) 132 | file(APPEND ${bat_file} "\n") 133 | 134 | add_test(${test_name} ${bat_file}) 135 | endif(WIN32) 136 | 137 | endfunction(GR_ADD_TEST) 138 | -------------------------------------------------------------------------------- /cmake/Modules/GrVersion.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2013 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_VERSION_CMAKE) 21 | return() 22 | endif() 23 | set(__INCLUDED_GR_VERSION_CMAKE TRUE) 24 | 25 | #eventually, replace version.sh and fill in the variables below 26 | set(MAJOR_VERSION ${VERSION_INFO_MAJOR_VERSION}) 27 | set(API_COMPAT ${VERSION_INFO_API_COMPAT}) 28 | set(MINOR_VERSION ${VERSION_INFO_MINOR_VERSION}) 29 | set(MAINT_VERSION ${VERSION_INFO_MAINT_VERSION}) 30 | 31 | ######################################################################## 32 | # Extract the version string from git describe. 33 | ######################################################################## 34 | find_package(Git) 35 | 36 | if(GIT_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git) 37 | message(STATUS "Extracting version information from git describe...") 38 | execute_process( 39 | COMMAND ${GIT_EXECUTABLE} describe --always --abbrev=8 --long 40 | OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE 41 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 42 | ) 43 | else() 44 | set(GIT_DESCRIBE "v${MAJOR_VERSION}.${API_COMPAT}.x-xxx-xunknown") 45 | endif() 46 | 47 | ######################################################################## 48 | # Use the logic below to set the version constants 49 | ######################################################################## 50 | if("${MINOR_VERSION}" STREQUAL "git") 51 | # VERSION: 3.3git-xxx-gxxxxxxxx 52 | # DOCVER: 3.3git 53 | # LIBVER: 3.3git 54 | set(VERSION "${GIT_DESCRIBE}") 55 | set(DOCVER "${MAJOR_VERSION}.${API_COMPAT}${MINOR_VERSION}") 56 | set(LIBVER "${MAJOR_VERSION}.${API_COMPAT}${MINOR_VERSION}") 57 | set(RC_MINOR_VERSION "0") 58 | set(RC_MAINT_VERSION "0") 59 | elseif("${MAINT_VERSION}" STREQUAL "git") 60 | # VERSION: 3.3.1git-xxx-gxxxxxxxx 61 | # DOCVER: 3.3.1git 62 | # LIBVER: 3.3.1git 63 | set(VERSION "${GIT_DESCRIBE}") 64 | set(DOCVER "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}${MAINT_VERSION}") 65 | set(LIBVER "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}${MAINT_VERSION}") 66 | math(EXPR RC_MINOR_VERSION "${MINOR_VERSION} - 1") 67 | set(RC_MAINT_VERSION "0") 68 | else() 69 | # This is a numbered release. 70 | # VERSION: 3.3.1{.x} 71 | # DOCVER: 3.3.1{.x} 72 | # LIBVER: 3.3.1{.x} 73 | if("${MAINT_VERSION}" STREQUAL "0") 74 | set(VERSION "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}") 75 | else() 76 | set(VERSION "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}.${MAINT_VERSION}") 77 | endif() 78 | set(DOCVER "${VERSION}") 79 | set(LIBVER "${VERSION}") 80 | set(RC_MINOR_VERSION ${MINOR_VERSION}) 81 | set(RC_MAINT_VERSION ${MAINT_VERSION}) 82 | endif() 83 | -------------------------------------------------------------------------------- /dsd_block_ff.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 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 | #ifndef INCLUDED_DSD_BLOCK_FF_H 23 | #define INCLUDED_DSD_BLOCK_FF_H 24 | 25 | #include 26 | #include 27 | 28 | /* 29 | extern "C" 30 | { 31 | #include 32 | } 33 | */ 34 | 35 | #define NZEROS 60 36 | 37 | struct mbe_parameters 38 | { 39 | float w0; 40 | int L; 41 | int K; 42 | int Vl[57]; 43 | float Ml[57]; 44 | float log2Ml[57]; 45 | float PHIl[57]; 46 | float PSIl[57]; 47 | float gamma; 48 | int un; 49 | int repeat; 50 | }; 51 | 52 | typedef struct mbe_parameters mbe_parms; 53 | 54 | typedef struct 55 | { 56 | int onesymbol; 57 | char mbe_in_file[1024]; 58 | FILE *mbe_in_f; 59 | int errorbars; 60 | int datascope; 61 | int symboltiming; 62 | int verbose; 63 | int p25enc; 64 | int p25lc; 65 | int p25status; 66 | int p25tg; 67 | int scoperate; 68 | char audio_in_dev[1024]; 69 | int audio_in_fd; 70 | char audio_out_dev[1024]; 71 | int audio_out_fd; 72 | int split; 73 | int playoffset; 74 | char mbe_out_dir[1024]; 75 | char mbe_out_file[1024]; 76 | FILE *mbe_out_f; 77 | float audio_gain; 78 | int audio_out; 79 | char wav_out_file[1024]; 80 | FILE *wav_out_f; 81 | int wav_out_fd; 82 | int serial_baud; 83 | char serial_dev[1024]; 84 | int serial_fd; 85 | int resume; 86 | int frame_dstar; 87 | int frame_x2tdma; 88 | int frame_p25p1; 89 | int frame_nxdn48; 90 | int frame_nxdn96; 91 | int frame_dmr; 92 | int frame_provoice; 93 | int mod_c4fm; 94 | int mod_qpsk; 95 | int mod_gfsk; 96 | int uvquality; 97 | int inverted_x2tdma; 98 | int inverted_dmr; 99 | int mod_threshold; 100 | int ssize; 101 | int msize; 102 | int playfiles; 103 | int delay; 104 | } dsd_opts; 105 | 106 | typedef struct 107 | { 108 | int *dibit_buf; 109 | int *dibit_buf_p; 110 | int repeat; 111 | short *audio_out_buf; 112 | short *audio_out_buf_p; 113 | float *audio_out_float_buf; 114 | float *audio_out_float_buf_p; 115 | float audio_out_temp_buf[160]; 116 | float *audio_out_temp_buf_p; 117 | int audio_out_idx; 118 | int audio_out_idx2; 119 | int wav_out_bytes; 120 | int center; 121 | int jitter; 122 | int synctype; 123 | int min; 124 | int max; 125 | int lmid; 126 | int umid; 127 | int minref; 128 | int maxref; 129 | int lastsample; 130 | int sbuf[128]; 131 | int sidx; 132 | int maxbuf[1024]; 133 | int minbuf[1024]; 134 | int midx; 135 | char err_str[64]; 136 | char fsubtype[16]; 137 | char ftype[16]; 138 | int symbolcnt; 139 | int rf_mod; 140 | int numflips; 141 | int lastsynctype; 142 | int lastp25type; 143 | int offset; 144 | int carrier; 145 | char tg[25][16]; 146 | int tgcount; 147 | int lasttg; 148 | int lastsrc; 149 | int nac; 150 | int errs; 151 | int errs2; 152 | int mbe_file_type; 153 | int optind; 154 | int numtdulc; 155 | int firstframe; 156 | char slot0light[8]; 157 | char slot1light[8]; 158 | float aout_gain; 159 | float aout_max_buf[200]; 160 | float *aout_max_buf_p; 161 | int aout_max_buf_idx; 162 | int samplesPerSymbol; 163 | int symbolCenter; 164 | char algid[9]; 165 | char keyid[17]; 166 | int currentslot; 167 | mbe_parms *cur_mp; 168 | mbe_parms *prev_mp; 169 | mbe_parms *prev_mp_enhanced; 170 | int p25kid; 171 | pthread_mutex_t input_mutex; 172 | pthread_cond_t input_ready; 173 | const float *input_samples; 174 | int input_length; 175 | int input_offset; 176 | 177 | pthread_mutex_t output_mutex; 178 | pthread_cond_t output_ready; 179 | short *output_buffer; 180 | int output_offset; 181 | float *output_samples; 182 | int output_num_samples; 183 | int output_length; 184 | int output_finished; 185 | float xv[NZEROS+1]; 186 | } dsd_state; 187 | 188 | 189 | 190 | enum dsd_frame_mode { 191 | dsd_FRAME_AUTO_DETECT, 192 | dsd_FRAME_P25_PHASE_1, 193 | dsd_FRAME_DSTAR, 194 | dsd_FRAME_NXDN48_IDAS, 195 | dsd_FRAME_NXDN96, 196 | dsd_FRAME_PROVOICE, 197 | dsd_FRAME_DMR_MOTOTRBO, 198 | dsd_FRAME_X2_TDMA 199 | }; 200 | 201 | enum dsd_modulation_optimizations { 202 | dsd_MOD_AUTO_SELECT, 203 | dsd_MOD_C4FM, 204 | dsd_MOD_GFSK, 205 | dsd_MOD_QPSK 206 | }; 207 | 208 | typedef struct 209 | { 210 | int num; 211 | dsd_opts opts; 212 | dsd_state state; 213 | } dsd_params; 214 | 215 | class dsd_block_ff; 216 | 217 | /* 218 | * We use boost::shared_ptr's instead of raw pointers for all access 219 | * to gr_blocks (and many other data structures). The shared_ptr gets 220 | * us transparent reference counting, which greatly simplifies storage 221 | * management issues. This is especially helpful in our hybrid 222 | * C++ / Python system. 223 | * 224 | * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm 225 | * 226 | * As a convention, the _sptr suffix indicates a boost::shared_ptr 227 | */ 228 | typedef boost::shared_ptr dsd_block_ff_sptr; 229 | 230 | /*! 231 | * \brief Return a shared_ptr to a new instance of dsd_block_ff. 232 | * 233 | * To avoid accidental use of raw pointers, dsd_block_ff's 234 | * constructor is private. dsd_make_block_ff is the public 235 | * interface for creating new instances. 236 | */ 237 | DSD_API dsd_block_ff_sptr dsd_make_block_ff (dsd_frame_mode frame = dsd_FRAME_AUTO_DETECT, 238 | dsd_modulation_optimizations mod = dsd_MOD_AUTO_SELECT, 239 | int uvquality = 3, bool errorbars = true, int verbosity = 2, bool empty = false, int num=-1); 240 | 241 | /*! 242 | * \brief pass discriminator output through Digital Speech Decoder 243 | * \ingroup block 244 | */ 245 | //class DSD_API dsd_block_ff : public gr_sync_decimator 246 | class DSD_API dsd_block_ff : public gr_block 247 | { 248 | private: 249 | // The friend declaration allows dsd_make_block_ff to 250 | // access the private constructor. 251 | 252 | friend DSD_API dsd_block_ff_sptr dsd_make_block_ff (dsd_frame_mode frame, dsd_modulation_optimizations mod, int uvquality, bool errorbars, int verbosity, bool empty, int num); 253 | 254 | dsd_params params; 255 | 256 | /*! 257 | * \brief pass discriminator output thread Digital Speech Decoder 258 | */ 259 | dsd_block_ff (dsd_frame_mode frame, dsd_modulation_optimizations mod, int uvquality, bool errorbars, int verbosity, bool empty, int num); // private constructor 260 | bool empty_frames; 261 | 262 | public: 263 | ~dsd_block_ff (); // public destructor 264 | 265 | // Where all the action really happens 266 | 267 | int close(); 268 | int general_work (int noutput_items, 269 | gr_vector_int &ninput_items, 270 | gr_vector_const_void_star &input_items, 271 | gr_vector_void_star &output_items); 272 | /* 273 | int work (int noutput_items, 274 | gr_vector_const_void_star &input_items, 275 | gr_vector_void_star &output_items);*/ 276 | }; 277 | 278 | #endif /* INCLUDED_DSD_BLOCK_FF_H */ 279 | -------------------------------------------------------------------------------- /example_start.sh: -------------------------------------------------------------------------------- 1 | ./smartnet --freq 856187500.0 --center 857000000.0 --rate 4000000 --error -5500 --rfgain 14 --ifgain 35 --bbgain 35 --tg 1616 2 | #./smartnet --freq 496444500.0 --center 496000000.0 --rate 1000000 --error 0 --rfgain 14 --ifgain 30 --bbgain 30 3 | 4 | 5 | #./smartnet --freq 856187500.0 --center 856207500.0 --rate 2000000 --error -5500 --rfgain 10 --ifgain 20 --bbgain 20 6 | 7 | #./smartnet --freq 855218500.0 --center 855000000.0 --rate 2000000 --error 0 --rfgain 14 --ifgain 25 --bbgain 25 8 | -------------------------------------------------------------------------------- /fsk_demod.cc: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | fsk_demod_sptr 10 | smartnet_make_fsk_demod () 11 | { 12 | return fsk_demod_sptr (new fsk_demod()); 13 | } 14 | 15 | static const int MIN_IN = 1; // mininum number of input streams 16 | static const int MAX_IN = 1; // maximum number of input streams 17 | static const int MIN_OUT = 1; // minimum number of output streams 18 | static const int MAX_OUT = 1; // maximum number of output streams 19 | 20 | fsk_demod::fsk_demod () 21 | : gr_block ("fsk_demod", 22 | gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)), 23 | gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (char))) 24 | { 25 | // nothing else required in this example 26 | } 27 | 28 | fsk_demod::~fsk_demod () 29 | { 30 | // nothing else required in this example 31 | } 32 | 33 | int fsk_demod::general_work (int noutput_items, 34 | gr_vector_int &ninput_items, 35 | gr_vector_const_void_star &input_items, 36 | gr_vector_void_star &output_items) 37 | { 38 | const float *in = (const float *) input_items[0]; 39 | float *out = (float *) output_items[0]; 40 | 41 | for (int i = 0; i < noutput_items; i++){ 42 | out[i] = in[i] * in[i]; 43 | } 44 | 45 | consume_each (noutput_items); 46 | 47 | // Tell runtime system how many output items we produced. 48 | return noutput_items; 49 | } 50 | -------------------------------------------------------------------------------- /fsk_demod.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_FSK_DEMOD_H 2 | #define INCLUDED_FSK_DEMOD_H 3 | 4 | #include 5 | 6 | class fsk_demod; 7 | 8 | typedef boost::shared_ptr fsk_demod_sptr; 9 | 10 | fsk_demod_sptr smartnet_make_fsk_demod(); 11 | 12 | 13 | class fsk_demod : public gr_block 14 | { 15 | private: 16 | // The friend declaration allows smartnet_make_deinterleave to 17 | // access the private constructor. 18 | 19 | friend fsk_demod_sptr smartnet_make_fsk_demod(); 20 | 21 | fsk_demod(); // private constructor 22 | 23 | public: 24 | ~fsk_demod(); // public destructor 25 | 26 | int general_work ( int noutput_items, 27 | gr_vector_int &ninput_items, 28 | gr_vector_const_void_star &input_items, 29 | gr_vector_void_star &output_items); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /scanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotastic/smartnet-scanner/0b22d422ac0f2123381585254bb28cab9b3b603e/scanner.png -------------------------------------------------------------------------------- /smartnet.cc: -------------------------------------------------------------------------------- 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 | 23 | /* 24 | * GNU Radio C++ example creating dial tone 25 | * ("the simplest thing that could possibly work") 26 | * 27 | * Send a tone each to the left and right channels of stereo audio 28 | * output and let the user's brain sum them. 29 | * 30 | * GNU Radio makes extensive use of Boost shared pointers. Signal processing 31 | * blocks are typically created by calling a "make" factory function, which 32 | * returns an instance of the block as a typedef'd shared pointer that can 33 | * be used in any way a regular pointer can. Shared pointers created this way 34 | * keep track of their memory and free it at the right time, so the user 35 | * doesn't need to worry about it (really). 36 | * 37 | */ 38 | 39 | // Include header files for each block used in flowgraph 40 | 41 | #include 42 | #include 43 | //#include 44 | #include 45 | #include 46 | 47 | #include "audio_receiver_dsd.h" 48 | #include "talkgroup.h" 49 | #include "smartnet_crc.h" 50 | #include "smartnet_deinterleave.h" 51 | 52 | #include 53 | #include 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include 62 | #include 63 | 64 | #include 65 | #include 66 | #include 67 | 68 | #include 69 | #include 70 | 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | #include 82 | #include 83 | 84 | #include 85 | #include 86 | #include 87 | #include // copy 88 | #include 89 | 90 | 91 | 92 | 93 | 94 | namespace po = boost::program_options; 95 | 96 | using namespace std; 97 | using namespace boost; 98 | 99 | int lastcmd = 0; 100 | double center_freq; 101 | int tg; 102 | 103 | WINDOW *active_tg_win; 104 | WINDOW *tg_menu_win; 105 | WINDOW *status_win; 106 | MENU *tg_menu; 107 | 108 | 109 | //log_dsd_sptr log_dsd; 110 | 111 | gr_top_block_sptr tb; 112 | osmosdr_source_c_sptr src; 113 | log_dsd_sptr rx; 114 | vector talkgroups; 115 | vector monitored_tg; 116 | char **menu_choices; 117 | ITEM **tg_menu_items; 118 | Talkgroup *active_tg; 119 | bool is_active; 120 | 121 | void update_active_tg_win() { 122 | werase(active_tg_win); 123 | box(active_tg_win, 0, 0); 124 | if (active_tg == NULL) { 125 | mvwprintw(active_tg_win,1,2,"TG: "); 126 | 127 | mvwprintw(active_tg_win,1,40,"Num: "); 128 | mvwprintw(active_tg_win,2,40,"Tag: "); 129 | mvwprintw(active_tg_win,2,60,"Group: "); 130 | } else { 131 | mvwprintw(active_tg_win,1,2,"TG: %s", active_tg->alpha_tag.c_str()); 132 | mvwprintw(active_tg_win,2,2,"%s ", active_tg->description.c_str()); 133 | mvwprintw(active_tg_win,1,40,"Num: %5lu", active_tg->number); 134 | mvwprintw(active_tg_win,2,40,"Tag: %s", active_tg->tag.c_str()); 135 | mvwprintw(active_tg_win,2,60,"Group: %s", active_tg->group.c_str()); 136 | } 137 | 138 | mvwprintw(active_tg_win,5,2,"Monitoring: "); 139 | for(std::vector::iterator it = monitored_tg.begin(); it != monitored_tg.end(); ++it) { 140 | Talkgroup *tg = (Talkgroup *) *it; 141 | wprintw(active_tg_win, "%s | ", tg->alpha_tag.c_str()); 142 | } 143 | 144 | wrefresh(active_tg_win); 145 | 146 | } 147 | void update_status_win(char *c) { 148 | wclear(status_win); 149 | //wattron(status_win,A_REVERSE); 150 | mvwprintw(status_win,0,2,"%s",c); 151 | wrefresh(status_win); 152 | } 153 | void create_status_win() { 154 | int startx, starty, width, height; 155 | 156 | height = 1; 157 | width = COLS; 158 | starty = LINES-1; 159 | startx = 0; 160 | 161 | status_win = newwin(height, width, starty, startx); 162 | } 163 | void create_active_tg_win() { 164 | int startx, starty, width, height; 165 | 166 | height = 10; 167 | width = COLS; 168 | starty = 0; 169 | startx = 0; 170 | 171 | active_tg_win = newwin(height, width, starty, startx); 172 | box(active_tg_win, 0, 0); 173 | 174 | wrefresh(active_tg_win); 175 | } 176 | 177 | void create_tg_menu() { 178 | std::string s; 179 | int n_choices, i; 180 | char *c; 181 | 182 | //printw("%s\n", s.c_str()); 183 | menu_choices = new char*[talkgroups.size()]; 184 | //menu_choices = malloc(talkgroups.size(), sizeof(char *)); 185 | i=0; 186 | for(std::vector::iterator it = talkgroups.begin(); it != talkgroups.end(); ++it) { 187 | 188 | Talkgroup *tg = (Talkgroup *) *it; 189 | s = tg->menu_string(); 190 | c = (char *) malloc((s.size() + 1) * sizeof(char)); 191 | //strncpy(c, s.c_str(), s.size()); 192 | //c[s.size()] = '\0'; 193 | strcpy(c, s.c_str()); 194 | menu_choices[i] = c; 195 | i++; 196 | } 197 | 198 | n_choices = talkgroups.size(); //ARRAY_SIZE(menu_choices); 199 | tg_menu_items = (ITEM **) calloc(n_choices + 1, sizeof(ITEM *)); 200 | 201 | 202 | for (i=0; i < n_choices; ++i) { 203 | tg_menu_items[i] = new_item(menu_choices[i], menu_choices[i]); 204 | set_item_userptr(tg_menu_items[i], (void *) talkgroups[i]); 205 | } 206 | 207 | tg_menu = new_menu((ITEM **) tg_menu_items); 208 | 209 | tg_menu_win = newwin(LINES - 11, COLS, 10, 0); 210 | keypad(tg_menu_win, TRUE); 211 | 212 | 213 | set_menu_win(tg_menu, tg_menu_win); 214 | set_menu_sub(tg_menu, derwin(tg_menu_win, LINES - 15, COLS - 4, 2, 2)); 215 | set_menu_format(tg_menu, LINES - 14 , 1); 216 | //set_menu_mark(tg_menu, " * "); 217 | box(tg_menu_win,0,0); 218 | menu_opts_off(tg_menu, O_SHOWDESC | O_ONEVALUE); 219 | //menu_opts_off(tg_menu, O_ONEVALUE); 220 | 221 | post_menu(tg_menu); 222 | 223 | } 224 | 225 | float getfreq(int cmd) { 226 | float freq; 227 | if (cmd < 0x1b8) { 228 | freq = float(cmd * 0.025 + 851.0125); 229 | } else if (cmd < 0x230) { 230 | freq = float(cmd * 0.025 + 851.0125 - 10.9875); 231 | } else { 232 | freq = 0; 233 | } 234 | 235 | return freq; 236 | } 237 | 238 | void parse_file(string filename) { 239 | ifstream in(filename.c_str()); 240 | if (!in.is_open()) return; 241 | 242 | boost::char_separator sep(","); 243 | typedef boost::tokenizer< boost::char_separator > t_tokenizer; 244 | 245 | vector< string > vec; 246 | string line; 247 | 248 | 249 | while (getline(in,line)) 250 | { 251 | 252 | t_tokenizer tok(line, sep); 253 | //Tokenizer tok(line); 254 | vec.assign(tok.begin(),tok.end()); 255 | 256 | if (vec.size() < 7) continue; 257 | 258 | Talkgroup *tg = new Talkgroup(atoi( vec[0].c_str()), vec[2].at(0),vec[3].c_str(),vec[4].c_str(),vec[5].c_str() ,vec[6].c_str()); 259 | 260 | talkgroups.push_back(tg); 261 | 262 | 263 | } 264 | 265 | } 266 | 267 | float parse_message(string s) { 268 | float retfreq = 0; 269 | bool rxfound = false; 270 | std::vector x; 271 | boost::split(x, s, boost::is_any_of(","), boost::token_compress_on); 272 | //vector x = split(s, ","); 273 | int address = atoi( x[0].c_str() ) & 0xFFF0; 274 | int groupflag = atoi( x[1].c_str() ); 275 | int command = atoi( x[2].c_str() ); 276 | 277 | 278 | 279 | if (command < 0x2d0) { 280 | 281 | if ( lastcmd == 0x308) { 282 | // Channel Grant 283 | if ((address != 56016) && (address != 8176)) { 284 | retfreq = getfreq(command); 285 | } 286 | } else { 287 | // Call continuation 288 | if ((address != 56016) && (address != 8176)) { 289 | retfreq = getfreq(command); 290 | } 291 | } 292 | } 293 | 294 | if (retfreq) { 295 | char c[100]; 296 | 297 | if (!is_active) { 298 | for(std::vector::iterator it = monitored_tg.begin(); it != monitored_tg.end(); ++it) { 299 | Talkgroup *target = (Talkgroup *) *it; 300 | if (target->number == address) { 301 | tb->lock(); 302 | rx->tune_offset(retfreq); 303 | rx->set_talkgroup(address); 304 | rx->unmute(); 305 | tb->unlock(); 306 | active_tg = target; 307 | is_active = true; 308 | break; 309 | } 310 | } 311 | 312 | } else { 313 | if (rx->get_talkgroup() == address) { 314 | 315 | if (rx->get_freq() != retfreq) { 316 | tb->lock(); 317 | rx->tune_offset(retfreq); 318 | rx->unmute(); 319 | tb->unlock(); 320 | } 321 | rx->active(); 322 | 323 | } else { 324 | if (rx->get_freq() == retfreq) { 325 | tb->lock(); 326 | rx->mute(); 327 | tb->unlock(); 328 | is_active = false; 329 | active_tg = NULL; 330 | } 331 | } 332 | } 333 | sprintf(c,"RX - Talkgroup: %5d Freq: %5g", address,retfreq); 334 | update_status_win(c); 335 | update_active_tg_win(); 336 | } 337 | 338 | if ((is_active) && (rx->rx_timeout() > 5.0)) { 339 | 340 | 341 | tb->lock(); 342 | rx->mute(); 343 | tb->unlock(); 344 | is_active = false; 345 | active_tg = NULL; 346 | update_active_tg_win(); 347 | } 348 | 349 | //cout << "Command: " << command << " Address: " << address << "\t GroupFlag: " << groupflag << " Freq: " << retfreq << endl; 350 | 351 | lastcmd = command; 352 | 353 | 354 | return retfreq; 355 | } 356 | 357 | 358 | int main(int argc, char **argv) 359 | { 360 | std::string device_addr; 361 | double samp_rate, chan_freq, error; 362 | int if_gain, bb_gain, rf_gain; 363 | //setup the program options 364 | po::options_description desc("Allowed options"); 365 | desc.add_options() 366 | ("help", "help message") 367 | ("arg", po::value(&device_addr)->default_value(""), "the device arguments in string format") 368 | ("rate", po::value(&samp_rate)->default_value(1e6), "the sample rate in samples per second") 369 | ("center", po::value(¢er_freq)->default_value(10e6), "the center frequency in Hz") 370 | ("error", po::value(&error)->default_value(0), "the Error in frequency in Hz") 371 | ("freq", po::value(&chan_freq)->default_value(10e6), "the frequency in Hz of the trunking channel") 372 | ("rfgain", po::value(&rf_gain)->default_value(14), "RF Gain") 373 | ("bbgain", po::value(&bb_gain)->default_value(25), "BB Gain") 374 | ("ifgain", po::value(&if_gain)->default_value(25), "IF Gain") 375 | ("tg", po::value(&tg)->default_value(0), "Talkgroup # in decimal format") 376 | ; 377 | po::variables_map vm; 378 | po::store(po::parse_command_line(argc, argv, desc), vm); 379 | po::notify(vm); 380 | 381 | //print the help message 382 | if (vm.count("help")){ 383 | std::cout 384 | << boost::format("SmartNet Trunking Scanner %s") % desc << std::endl 385 | << "The tags sink demo block will print USRP source time stamps." << std::endl 386 | << "The tags source demo block will send bursts to the USRP sink." << std::endl 387 | << "Look at the USRP output on a scope to see the timed bursts." << std::endl 388 | << std::endl; 389 | return ~0; 390 | } 391 | 392 | 393 | 394 | 395 | 396 | tb = gr_make_top_block("smartnet"); 397 | 398 | 399 | src = osmosdr_make_source_c(); 400 | cout << "Setting sample rate to: " << samp_rate << endl; 401 | src->set_sample_rate(samp_rate); 402 | cout << "Tunning to " << center_freq - error << "hz" << endl; 403 | src->set_center_freq(center_freq - error,0); 404 | 405 | cout << "Setting RF gain to " << rf_gain << endl; 406 | cout << "Setting BB gain to " << bb_gain << endl; 407 | cout << "Setting IF gain to " << if_gain << endl; 408 | 409 | src->set_gain(rf_gain); 410 | src->set_if_gain(if_gain); 411 | src->set_bb_gain(bb_gain); 412 | 413 | 414 | 415 | 416 | float samples_per_second = samp_rate; 417 | float syms_per_sec = 3600; 418 | float gain_mu = 0.01; 419 | float mu=0.5; 420 | float omega_relative_limit = 0.3; 421 | float offset = center_freq - chan_freq; 422 | float clockrec_oversample = 3; 423 | int decim = int(samples_per_second / (syms_per_sec * clockrec_oversample)); 424 | float sps = samples_per_second/decim/syms_per_sec; 425 | const double pi = boost::math::constants::pi(); 426 | 427 | gr_msg_queue_sptr queue = gr_make_msg_queue(); 428 | 429 | 430 | gr_sig_source_c_sptr offset_sig = gr_make_sig_source_c(samp_rate, GR_SIN_WAVE, offset, 1.0, 0.0); 431 | 432 | gr_multiply_cc_sptr mixer = gr_make_multiply_cc(); 433 | 434 | gr_fir_filter_ccf_sptr downsample = gr_make_fir_filter_ccf(decim, gr_firdes::low_pass(1, samples_per_second, 10000, 5000, gr_firdes::WIN_HANN)); 435 | 436 | /*prefilter = gr_make_freq_xlating_fir_filter_ccf(decim, 437 | gr_firdes::low_pass(1, samp_rate, xlate_bandwidth/2, 6000), 438 | offset, 439 | samp_rate);*/ 440 | 441 | //gr::filter::freq_xlating_fir_filter_ccf::sptr downsample = gr::filter::freq_xlating_fir_filter_ccf::make(decim, gr::filter::firdes::low_pass(1, samples_per_second, 10000, 1000, gr::filter::firdes::WIN_HANN), 0,samples_per_second); 442 | 443 | gr_pll_freqdet_cf_sptr pll_demod = gr_make_pll_freqdet_cf(2.0 / clockrec_oversample, 2*pi/clockrec_oversample, 444 | -2*pi/clockrec_oversample); 445 | 446 | digital_fll_band_edge_cc_sptr carriertrack = digital_make_fll_band_edge_cc(sps, 0.6, 64, 1.0); 447 | 448 | digital_clock_recovery_mm_ff_sptr softbits = digital_make_clock_recovery_mm_ff(sps, 0.25 * gain_mu * gain_mu, mu, gain_mu, omega_relative_limit); 449 | 450 | 451 | digital_binary_slicer_fb_sptr slicer = digital_make_binary_slicer_fb(); 452 | gr_correlate_access_code_tag_bb_sptr start_correlator = gr_make_correlate_access_code_tag_bb("10101100",0,"smartnet_preamble"); 453 | 454 | 455 | smartnet_deinterleave_sptr deinterleave = smartnet_make_deinterleave(); 456 | 457 | smartnet_crc_sptr crc = smartnet_make_crc(queue); 458 | 459 | rx = make_log_dsd( chan_freq, center_freq,tg, samp_rate); 460 | 461 | //audio_sink::sptr sink = audio_make_sink(44100); 462 | 463 | 464 | 465 | tb->connect(offset_sig, 0, mixer, 0); 466 | tb->connect(src, 0, mixer, 1); 467 | tb->connect(mixer, 0, downsample, 0); 468 | tb->connect(downsample, 0, carriertrack, 0); 469 | tb->connect(carriertrack, 0, pll_demod, 0); 470 | tb->connect(pll_demod, 0, softbits, 0); 471 | tb->connect(softbits, 0, slicer, 0); 472 | tb->connect(slicer, 0, start_correlator, 0); 473 | tb->connect(start_correlator, 0, deinterleave, 0); 474 | tb->connect(deinterleave, 0, crc, 0); 475 | 476 | tb->connect(src, 0, rx, 0); 477 | 478 | 479 | is_active = false; 480 | active_tg = NULL; 481 | tb->start(); 482 | initscr(); 483 | cbreak(); 484 | noecho(); 485 | nodelay(tg_menu_win,TRUE); 486 | 487 | parse_file("ChanList.csv"); 488 | create_status_win(); 489 | create_active_tg_win(); 490 | update_active_tg_win(); 491 | 492 | create_tg_menu(); 493 | wrefresh(tg_menu_win); 494 | update_status_win("Initialized..."); 495 | int c; 496 | 497 | 498 | 499 | while (1) { 500 | if (!queue->empty_p()) 501 | { 502 | std::string sentence; 503 | gr_message_sptr msg; 504 | msg = queue->delete_head(); 505 | sentence = msg->to_string(); 506 | parse_message(sentence); 507 | } else { 508 | 509 | boost::this_thread::sleep(boost::posix_time::milliseconds(1.0/10)); 510 | } 511 | wtimeout(tg_menu_win, 0); 512 | c = wgetch(tg_menu_win); 513 | switch(c) 514 | { 515 | 516 | case KEY_DOWN: 517 | menu_driver(tg_menu, REQ_DOWN_ITEM); 518 | wrefresh(tg_menu_win); 519 | break; 520 | case KEY_UP: 521 | menu_driver(tg_menu, REQ_UP_ITEM); 522 | wrefresh(tg_menu_win); 523 | break; 524 | case KEY_LEFT: 525 | menu_driver(tg_menu, REQ_LEFT_ITEM); 526 | wrefresh(tg_menu_win); 527 | break; 528 | case KEY_RIGHT: 529 | menu_driver(tg_menu, REQ_RIGHT_ITEM); 530 | wrefresh(tg_menu_win); 531 | break; 532 | case KEY_NPAGE: 533 | menu_driver(tg_menu, REQ_SCR_DPAGE); 534 | wrefresh(tg_menu_win); 535 | break; 536 | case KEY_PPAGE: 537 | menu_driver(tg_menu, REQ_SCR_UPAGE); 538 | wrefresh(tg_menu_win); 539 | break; 540 | case ' ': 541 | ITEM **items; 542 | Talkgroup *tg; 543 | 544 | 545 | menu_driver(tg_menu, REQ_TOGGLE_ITEM); 546 | 547 | monitored_tg.clear(); 548 | items = menu_items(tg_menu); 549 | 550 | for(int i = 0; i < item_count(tg_menu); ++i) 551 | if(item_value(items[i]) == TRUE) 552 | { 553 | tg = (Talkgroup *) item_userptr(items[i]);; 554 | monitored_tg.push_back(tg); 555 | } 556 | 557 | wrefresh(tg_menu_win); 558 | update_active_tg_win(); 559 | break; 560 | } 561 | 562 | 563 | 564 | 565 | } 566 | 567 | endwin(); 568 | 569 | // Exit normally. 570 | return 0; 571 | } 572 | -------------------------------------------------------------------------------- /smartnet_crc.cc: -------------------------------------------------------------------------------- 1 | //smartnet_crc.cc 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2012 Nick Foster 5 | * 6 | * This file is part of gr_smartnet 7 | * 8 | * gr_smartnet 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 | * gr_smartnet 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 | #ifdef HAVE_CONFIG_H 25 | #include "config.h" 26 | #endif 27 | 28 | #include "smartnet_crc.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "smartnet_types.h" 34 | 35 | #define VERBOSE 0 36 | 37 | /* 38 | * Create a new instance of smartnet_crc and return 39 | * a boost shared_ptr. This is effectively the public constructor. 40 | */ 41 | smartnet_crc_sptr smartnet_make_crc(gr_msg_queue_sptr queue) 42 | { 43 | return smartnet_crc_sptr (new smartnet_crc (queue)); 44 | } 45 | 46 | smartnet_crc::smartnet_crc (gr_msg_queue_sptr queue) 47 | : gr_sync_block ("crc", 48 | gr_make_io_signature (1, 1, sizeof (char)), 49 | gr_make_io_signature (0, 0, 0)) 50 | { 51 | set_output_multiple(38); 52 | d_queue = queue; 53 | } 54 | 55 | /* 56 | * Our virtual destructor. 57 | */ 58 | smartnet_crc::~smartnet_crc () 59 | { 60 | //nothing else required in this example 61 | } 62 | 63 | static void smartnet_ecc(char *out, const char *in) { 64 | char expected[76]; 65 | char syndrome[76]; 66 | 67 | //first we calculate the EXPECTED parity bits from the RECEIVED bitstream 68 | //parity is I[i] ^ I[i-1] 69 | //since the bitstream is still interleaved with the P bits, we can do this while running 70 | expected[0] = in[0] & 0x01; //info bit 71 | expected[1] = in[0] & 0x01; //this is a parity bit, prev bits were 0 so we call x ^ 0 = x 72 | for(int k = 2; k < 76*2; k+=2) { 73 | expected[k] = in[k] & 0x01; //info bit 74 | expected[k+1] = (in[k] & 0x01) ^ (in[k-2] & 0x01); //parity bit 75 | } 76 | 77 | for(int k = 0; k < 76; k++) { 78 | syndrome[k] = expected[k] ^ (in[k] & 0x01); //calculate the syndrome 79 | if(VERBOSE) if(syndrome[k]) std::cout << "Bit error at bit " << k << std::endl; 80 | } 81 | 82 | for(int k = 0; k < 38-1; k++) { 83 | //now we correct the data using the syndrome: if two consecutive 84 | //parity bits are flipped, you've got a bad previous bit 85 | if(syndrome[2*k+1] && syndrome[2*k+3]) { 86 | out[k] = (in[2*k] & 0x01) ? 0 : 1; //byte-safe bit flip 87 | if(VERBOSE) std::cout << "I just flipped a bit!" << std::endl; 88 | } 89 | else out[k] = in[2*k]; 90 | } 91 | } 92 | 93 | static bool crc(const char *in) { 94 | unsigned int crcaccum = 0x0393; 95 | unsigned int crcop = 0x036E; 96 | unsigned int crcgiven; 97 | 98 | //calc expected crc 99 | for(int j=0; j<27; j++) { 100 | if(crcop & 0x01) crcop = (crcop >> 1)^0x0225; 101 | else crcop >>= 1; 102 | if (in[j] & 0x01) crcaccum = crcaccum ^ crcop; 103 | } 104 | 105 | //load given crc 106 | crcgiven = 0x0000; 107 | for(int j=0; j<10; j++) { 108 | crcgiven <<= 1; 109 | crcgiven += !bool(in[j+27] & 0x01); 110 | } 111 | 112 | return (crcgiven == crcaccum); 113 | } 114 | 115 | static smartnet_packet parse(const char *in) { 116 | smartnet_packet pkt; 117 | 118 | pkt.address = 0; 119 | pkt.groupflag = false; 120 | pkt.command = 0; 121 | pkt.crc = 0; 122 | 123 | int i=0; 124 | 125 | for(int k = 15; k >=0 ; k--) pkt.address += (!bool(in[i++] & 0x01)) << k; //first 16 bits are ID, MSB first 126 | pkt.groupflag = !bool(in[i++]); 127 | for(int k = 9; k >=0 ; k--) pkt.command += (!bool(in[i++] & 0x01)) << k; //next 10 bits are command, MSB first 128 | for(int k = 9; k >=0 ; k--) pkt.crc += (!bool(in[i++] & 0x01)) << k; //next 10 bits are CRC 129 | i++; //skip the guard bit 130 | 131 | //now correct things according to the mottrunk.txt description 132 | pkt.address ^= 0x33C7; 133 | pkt.command ^= 0x032A; 134 | 135 | return pkt; 136 | } 137 | 138 | int 139 | smartnet_crc::work (int noutput_items, 140 | gr_vector_const_void_star &input_items, 141 | gr_vector_void_star &output_items) 142 | { 143 | const char *in = (const char *) input_items[0]; 144 | 145 | int size = noutput_items - 76; 146 | if(size <= 0) { 147 | return 0; //better luck next time 148 | } 149 | 150 | uint64_t abs_sample_cnt = nitems_read(0); 151 | std::vector frame_tags; 152 | 153 | get_tags_in_range(frame_tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::pmt_string_to_symbol("smartnet_frame")); 154 | if(frame_tags.size() == 0) { 155 | return 0; //sad trombone 156 | } 157 | 158 | std::vector::iterator tag_iter; 159 | for(tag_iter = frame_tags.begin(); tag_iter != frame_tags.end(); tag_iter++) { 160 | uint64_t mark = tag_iter->offset - abs_sample_cnt; 161 | if(VERBOSE) std::cout << "found a frame at " << mark << std::endl; 162 | 163 | char databits[38]; 164 | smartnet_ecc(databits, &in[mark]); 165 | bool crc_ok = crc(databits); 166 | 167 | if(crc_ok) { 168 | if(VERBOSE) std::cout << "CRC OK" << std::endl; 169 | //parse the message into readable chunks 170 | smartnet_packet pkt = parse(databits); 171 | 172 | //and throw it at the msgq 173 | std::ostringstream payload; 174 | payload.str(""); 175 | payload << pkt.address << "," << pkt.groupflag << "," << pkt.command; 176 | gr_message_sptr msg = gr_make_message_from_string(std::string(payload.str())); 177 | d_queue->handle(msg); 178 | } else if (VERBOSE) std::cout << "CRC FAILED" << std::endl; 179 | } 180 | return size; 181 | } 182 | -------------------------------------------------------------------------------- /smartnet_crc.h: -------------------------------------------------------------------------------- 1 | //smartnet_crc.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 smartnet_crc_H 24 | #define smartnet_crc_H 25 | 26 | #include 27 | #include 28 | 29 | class smartnet_crc; 30 | 31 | /* 32 | * We use boost::shared_ptr's instead of raw pointers for all access 33 | * to gr_blocks (and many other data structures). The shared_ptr gets 34 | * us transparent reference counting, which greatly simplifies storage 35 | * management issues. This is especially helpful in our hybrid 36 | * C++ / Python system. 37 | * 38 | * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm 39 | * 40 | * As a convention, the _sptr suffix indicates a boost::shared_ptr 41 | */ 42 | typedef boost::shared_ptr smartnet_crc_sptr; 43 | 44 | /*! 45 | * \brief Return a shared_ptr to a new instance of smartnet_crc. 46 | * 47 | * To avoid accidental use of raw pointers, smartnet_crc's 48 | * constructor is private. ais_make_invert is the public 49 | * interface for creating new instances. 50 | */ 51 | smartnet_crc_sptr smartnet_make_crc(gr_msg_queue_sptr queue); 52 | 53 | /*! 54 | * \brief invert a packed stream of bits. 55 | * \ingroup block 56 | * 57 | * 58 | * This uses the preferred technique: subclassing gr_crc_block. 59 | */ 60 | class smartnet_crc : public gr_sync_block 61 | { 62 | private: 63 | // The friend declaration allows smartnet_make_crc to 64 | // access the private constructor. 65 | 66 | friend smartnet_crc_sptr smartnet_make_crc(gr_msg_queue_sptr queue); 67 | 68 | smartnet_crc(gr_msg_queue_sptr queue); // private constructor 69 | gr_msg_queue_sptr d_queue; 70 | 71 | public: 72 | ~smartnet_crc(); // public destructor 73 | 74 | // Where all the action really happens 75 | 76 | int work (int noutput_items, 77 | gr_vector_const_void_star &input_items, 78 | gr_vector_void_star &output_items); 79 | }; 80 | 81 | #endif /* smartnet_crc_H */ 82 | 83 | -------------------------------------------------------------------------------- /smartnet_deinterleave.cc: -------------------------------------------------------------------------------- 1 | //smartnet_deinterleave.cc 2 | /* -*- c++ -*- */ 3 | /* 4 | * Copyright 2012 Nick Foster 5 | * 6 | * This file is part of gr_smartnet 7 | * 8 | * gr_smartnet 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 | * gr_smartnet 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 | #ifdef HAVE_CONFIG_H 25 | #include "config.h" 26 | #endif 27 | 28 | #include "smartnet_deinterleave.h" 29 | #include 30 | #include 31 | 32 | #define VERBOSE 0 33 | 34 | /* 35 | * Create a new instance of smartnet_deinterleave and return 36 | * a boost shared_ptr. This is effectively the public constructor. 37 | */ 38 | smartnet_deinterleave_sptr smartnet_make_deinterleave() 39 | { 40 | return smartnet_deinterleave_sptr (new smartnet_deinterleave ()); 41 | } 42 | 43 | /* 44 | * Specify constraints on number of input and output streams. 45 | * This info is used to construct the input and output signatures 46 | * (2nd & 3rd args to gr_block's constructor). The input and 47 | * output signatures are used by the runtime system to 48 | * check that a valid number and type of inputs and outputs 49 | * are connected to this block. In this case, we accept 50 | * only 1 input and 1 output. 51 | */ 52 | static const int MIN_IN = 1; // mininum number of input streams 53 | static const int MAX_IN = 1; // maximum number of input streams 54 | static const int MIN_OUT = 1; // minimum number of output streams 55 | static const int MAX_OUT = 1; // maximum number of output streams 56 | 57 | /* 58 | * The private constructor 59 | */ 60 | smartnet_deinterleave::smartnet_deinterleave () 61 | : gr_block ("deinterleave", 62 | gr_make_io_signature (MIN_IN, MAX_IN, sizeof (char)), 63 | gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (char))) 64 | { 65 | set_relative_rate((double)(76.0/84.0)); 66 | set_output_multiple(76); 67 | } 68 | 69 | /* 70 | * Our virtual destructor. 71 | */ 72 | smartnet_deinterleave::~smartnet_deinterleave () 73 | { 74 | // nothing else required in this example 75 | } 76 | 77 | void smartnet_deinterleave::forecast (int noutput_items, 78 | gr_vector_int &ninput_items_required) //estimate number of input samples required for noutput_items samples 79 | { 80 | int size = (noutput_items * 84) / 76; 81 | 82 | ninput_items_required[0] = size; 83 | } 84 | 85 | 86 | int 87 | smartnet_deinterleave::general_work (int noutput_items, 88 | gr_vector_int &ninput_items, 89 | gr_vector_const_void_star &input_items, 90 | gr_vector_void_star &output_items) 91 | { 92 | const char *in = (const char *) input_items[0]; 93 | char *out = (char *) output_items[0]; 94 | 95 | if(VERBOSE) std::cout << "Deinterleave called with " << noutput_items << " outputs" << std::endl; 96 | 97 | //you will need to look ahead 84 bits to post 76 bits of data 98 | //TODO this needs to be able to handle shorter frames while keeping state in order to end gracefully 99 | int size = ninput_items[0] - 84; 100 | if(size <= 0) { 101 | consume_each(0); 102 | return 0; //better luck next time 103 | } 104 | 105 | uint64_t abs_sample_cnt = nitems_read(0); 106 | std::vector preamble_tags; 107 | 108 | uint64_t outlen = 0; //output sample count 109 | 110 | get_tags_in_range(preamble_tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::pmt_string_to_symbol("smartnet_preamble")); 111 | if(preamble_tags.size() == 0) { 112 | consume_each(size); 113 | return 0; 114 | } 115 | 116 | std::vector::iterator tag_iter; 117 | for(tag_iter = preamble_tags.begin(); tag_iter != preamble_tags.end(); tag_iter++) { 118 | uint64_t mark = tag_iter->offset - abs_sample_cnt; 119 | 120 | if(VERBOSE) std::cout << "found a preamble at " << tag_iter->offset << std::endl; 121 | 122 | for(int k=0; k<76/4; k++) { 123 | for(int l=0; l<4; l++) { 124 | out[k*4 + l] = in[mark + k + l*19]; 125 | } 126 | } 127 | 128 | //since you're a nonsynchronized block, you have to reissue a 129 | //tag with the correct output sample number 130 | add_item_tag(0, //stream ID 131 | nitems_written(0) + mark, //sample 132 | pmt::pmt_string_to_symbol("smartnet_frame"), //key 133 | pmt::pmt_t() //data (unused here) 134 | ); 135 | outlen += 76; 136 | } 137 | 138 | if(VERBOSE) std::cout << "consumed " << size << ", produced " << outlen << std::endl; 139 | consume_each(preamble_tags.back().offset - abs_sample_cnt + 84); 140 | return outlen; 141 | } 142 | -------------------------------------------------------------------------------- /smartnet_deinterleave.h: -------------------------------------------------------------------------------- 1 | //smartnet_deinterleave.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 smartnet_deinterleave_H 24 | #define smartnet_deinterleave_H 25 | 26 | #include 27 | 28 | class smartnet_deinterleave; 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 smartnet_deinterleave_sptr; 42 | 43 | /*! 44 | * \brief Return a shared_ptr to a new instance of smartnet_deinterleave. 45 | * 46 | * To avoid accidental use of raw pointers, smartnet_deinterleave's 47 | * constructor is private. smartnet_make_deinterleave is the public 48 | * interface for creating new instances. 49 | */ 50 | smartnet_deinterleave_sptr smartnet_make_deinterleave(); 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 smartnet_deinterleave : public gr_block 60 | { 61 | private: 62 | // The friend declaration allows smartnet_make_deinterleave to 63 | // access the private constructor. 64 | 65 | friend smartnet_deinterleave_sptr smartnet_make_deinterleave(); 66 | 67 | smartnet_deinterleave(); // private constructor 68 | 69 | public: 70 | ~smartnet_deinterleave(); // public destructor 71 | 72 | // Where all the action really happens 73 | 74 | int general_work (int noutput_items, 75 | gr_vector_int &ninput_items, 76 | gr_vector_const_void_star &input_items, 77 | gr_vector_void_star &output_items); 78 | 79 | void forecast (int noutput_items, 80 | gr_vector_int &ninput_items_required); 81 | }; 82 | 83 | #endif /* smartnet_deinterleave_H */ 84 | 85 | -------------------------------------------------------------------------------- /smartnet_types.h: -------------------------------------------------------------------------------- 1 | //datatypes for smartnet decoder 2 | 3 | struct smartnet_packet { 4 | unsigned int address; 5 | bool groupflag; 6 | unsigned int command; 7 | unsigned int crc; 8 | }; 9 | -------------------------------------------------------------------------------- /talkgroup.cc: -------------------------------------------------------------------------------- 1 | #include "talkgroup.h" 2 | 3 | 4 | Talkgroup::Talkgroup(long num, char m, std::string a, std::string d, std::string t, std::string g) { 5 | number = num; 6 | mode = m; 7 | alpha_tag = a; 8 | description = d; 9 | tag = t; 10 | group = g; 11 | active = false; 12 | } 13 | 14 | std::string Talkgroup::menu_string() { 15 | char buff[150]; 16 | //std::ostringstream oss; 17 | 18 | sprintf(buff, "%5lu - %-15s %-20s %-15s %-40s", number, alpha_tag.c_str(), tag.c_str(), group.c_str(), description.c_str()); 19 | //sprintf(buff, "%5lu - %s", number, alpha_tag.c_str()); 20 | 21 | std::string buffAsStdStr = buff; 22 | 23 | return buffAsStdStr; 24 | } 25 | 26 | bool Talkgroup::is_active() { 27 | 28 | return active; 29 | } 30 | 31 | void Talkgroup::set_active(bool a) { 32 | 33 | active = a; 34 | } 35 | -------------------------------------------------------------------------------- /talkgroup.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //#include 4 | 5 | class Talkgroup { 6 | public: 7 | long number; 8 | char mode; 9 | std::string alpha_tag; 10 | std::string description; 11 | std::string tag; 12 | std::string group; 13 | Talkgroup(long num, char m, std::string a, std::string d, std::string t, std::string g); 14 | bool is_active(); 15 | void set_active(bool a); 16 | std::string menu_string(); 17 | private: 18 | bool active; 19 | 20 | }; 21 | --------------------------------------------------------------------------------