runtime: import minimal gr runtime for standalone mode (wip)

stripped pmt and message infrastructure, no logging, no nothing...
This commit is contained in:
Dimitri Stolnikov 2013-08-03 19:01:31 +02:00
parent 9dfe3a6354
commit be1314af10
135 changed files with 19735 additions and 9 deletions

View File

@ -97,6 +97,7 @@ MESSAGE(STATUS "Configuring Boost C++ Libraries...")
SET(BOOST_REQUIRED_COMPONENTS
thread
system
filesystem
)
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
@ -140,6 +141,26 @@ set(GR_LIBEXEC_DIR libexec)
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
# Special exception if prefix is /usr so we don't make a /usr/etc.
string(COMPARE EQUAL ${CMAKE_INSTALL_PREFIX} "/usr" isusr)
if(isusr)
set(SYSCONFDIR "/${GR_CONF_DIR}" CACHE PATH "System configuration directory")
else(isusr)
set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" CACHE PATH "System configuration directory" FORCE)
endif(isusr)
set(GR_PREFSDIR ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}/conf.d)
########################################################################
# Variables replaced when configuring the package config files
########################################################################
file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}" prefix)
file(TO_NATIVE_PATH "\${prefix}" exec_prefix)
file(TO_NATIVE_PATH "\${exec_prefix}/${GR_LIBRARY_DIR}" libdir)
file(TO_NATIVE_PATH "\${prefix}/${GR_INCLUDE_DIR}" includedir)
file(TO_NATIVE_PATH "${SYSCONFDIR}" SYSCONFDIR)
file(TO_NATIVE_PATH "${GR_PREFSDIR}" GR_PREFSDIR)
########################################################################
# Find build dependencies
########################################################################
@ -157,9 +178,41 @@ find_package(LibHackRF)
find_package(LibbladeRF)
find_package(Doxygen)
set(PYTHON_RUNTIME_CHECK TRUE)
if(NOT GNURADIO_RUNTIME_FOUND)
message(FATAL_ERROR "GnuRadio Runtime required to build " ${CMAKE_PROJECT_NAME})
endif()
message(STATUS "Enabling built-in GNU Radio runtime...")
set(RUNTIME_MODE TRUE CACHE INTERNAL "Built-in GNU Radio runtime")
add_subdirectory(include/osmosdr/runtime)
set(GNURADIO_RUNTIME_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include/osmosdr/runtime)
set(GNURADIO_RUNTIME_LIBRARY_DIRS "")
set(GNURADIO_RUNTIME_LIBRARIES "")
set(GNURADIO_PMT_INCLUDE_DIRS "")
set(GNURADIO_PMT_LIBRARY_DIRS "")
set(GNURADIO_PMT_LIBRARIES "")
set(GNURADIO_BLOCKS_INCLUDE_DIRS "")
set(GNURADIO_BLOCKS_LIBRARY_DIRS "")
set(GNURADIO_BLOCKS_LIBRARIES "")
LIST(APPEND GR_OSMOSDR_PC_CFLAGS "-I\${includedir}/osmosdr/runtime")
# disable python bindings as long as we don't have any swig files for the runtime
set(PYTHON_RUNTIME_CHECK FALSE)
endif(NOT GNURADIO_RUNTIME_FOUND)
if(GNURADIO_RUNTIME_FOUND)
LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-runtime")
endif(GNURADIO_RUNTIME_FOUND)
if(GNURADIO_PMT_FOUND)
LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-pmt")
endif(GNURADIO_PMT_FOUND)
if(GNURADIO_BLOCKS_FOUND)
LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-blocks")
endif(GNURADIO_BLOCKS_FOUND)
########################################################################
# Setup the include and linker paths
@ -211,10 +264,11 @@ if(SWIG_FOUND)
endif(SWIG_FOUND)
include(GrComponent)
GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON
GR_REGISTER_COMPONENT("Python bindings" ENABLE_PYTHON
PYTHONLIBS_FOUND
SWIG_FOUND
SWIG_VERSION_CHECK
PYTHON_RUNTIME_CHECK
)
########################################################################

58
cmake/msvc/config.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_CONFIG_H_ // [
#define _MSC_CONFIG_H_
////////////////////////////////////////////////////////////////////////
// enable inline functions for C code
////////////////////////////////////////////////////////////////////////
#ifndef __cplusplus
# define inline __inline
#endif
////////////////////////////////////////////////////////////////////////
// signed size_t
////////////////////////////////////////////////////////////////////////
#include <stddef.h>
typedef ptrdiff_t ssize_t;
////////////////////////////////////////////////////////////////////////
// rint functions
////////////////////////////////////////////////////////////////////////
#include <math.h>
static inline long lrint(double x){return (long)(x > 0.0 ? x + 0.5 : x - 0.5);}
static inline long lrintf(float x){return (long)(x > 0.0f ? x + 0.5f : x - 0.5f);}
static inline long long llrint(double x){return (long long)(x > 0.0 ? x + 0.5 : x - 0.5);}
static inline long long llrintf(float x){return (long long)(x > 0.0f ? x + 0.5f : x - 0.5f);}
static inline double rint(double x){return (x > 0.0)? floor(x + 0.5) : ceil(x - 0.5);}
static inline float rintf(float x){return (x > 0.0f)? floorf(x + 0.5f) : ceilf(x - 0.5f);}
////////////////////////////////////////////////////////////////////////
// math constants
////////////////////////////////////////////////////////////////////////
#define INFINITY HUGE_VAL
# define M_E 2.7182818284590452354 /* e */
# define M_LOG2E 1.4426950408889634074 /* log_2 e */
# define M_LOG10E 0.43429448190325182765 /* log_10 e */
# define M_LN2 0.69314718055994530942 /* log_e 2 */
# define M_LN10 2.30258509299404568402 /* log_e 10 */
# define M_PI 3.14159265358979323846 /* pi */
# define M_PI_2 1.57079632679489661923 /* pi/2 */
# define M_PI_4 0.78539816339744830962 /* pi/4 */
# define M_1_PI 0.31830988618379067154 /* 1/pi */
# define M_2_PI 0.63661977236758134308 /* 2/pi */
# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
////////////////////////////////////////////////////////////////////////
// random and srandom
////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
static inline long int random (void) { return rand(); }
static inline void srandom (unsigned int seed) { srand(seed); }
#endif // _MSC_CONFIG_H_ ]

301
cmake/msvc/inttypes.h Normal file
View File

@ -0,0 +1,301 @@
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_INTTYPES_H_ // [
#define _MSC_INTTYPES_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <stdint.h>
// 7.8 Format conversion of integer types
typedef struct {
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
// 7.8.1 Macros for format specifiers
// The fprintf macros for signed integers are:
#define PRId8 "d"
#define PRIi8 "i"
#define PRIdLEAST8 "d"
#define PRIiLEAST8 "i"
#define PRIdFAST8 "d"
#define PRIiFAST8 "i"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIdLEAST16 "hd"
#define PRIiLEAST16 "hi"
#define PRIdFAST16 "hd"
#define PRIiFAST16 "hi"
#define PRId32 "I32d"
#define PRIi32 "I32i"
#define PRIdLEAST32 "I32d"
#define PRIiLEAST32 "I32i"
#define PRIdFAST32 "I32d"
#define PRIiFAST32 "I32i"
#define PRId64 "I64d"
#define PRIi64 "I64i"
#define PRIdLEAST64 "I64d"
#define PRIiLEAST64 "I64i"
#define PRIdFAST64 "I64d"
#define PRIiFAST64 "I64i"
#define PRIdMAX "I64d"
#define PRIiMAX "I64i"
#define PRIdPTR "Id"
#define PRIiPTR "Ii"
// The fprintf macros for unsigned integers are:
#define PRIo8 "o"
#define PRIu8 "u"
#define PRIx8 "x"
#define PRIX8 "X"
#define PRIoLEAST8 "o"
#define PRIuLEAST8 "u"
#define PRIxLEAST8 "x"
#define PRIXLEAST8 "X"
#define PRIoFAST8 "o"
#define PRIuFAST8 "u"
#define PRIxFAST8 "x"
#define PRIXFAST8 "X"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRIoLEAST16 "ho"
#define PRIuLEAST16 "hu"
#define PRIxLEAST16 "hx"
#define PRIXLEAST16 "hX"
#define PRIoFAST16 "ho"
#define PRIuFAST16 "hu"
#define PRIxFAST16 "hx"
#define PRIXFAST16 "hX"
#define PRIo32 "I32o"
#define PRIu32 "I32u"
#define PRIx32 "I32x"
#define PRIX32 "I32X"
#define PRIoLEAST32 "I32o"
#define PRIuLEAST32 "I32u"
#define PRIxLEAST32 "I32x"
#define PRIXLEAST32 "I32X"
#define PRIoFAST32 "I32o"
#define PRIuFAST32 "I32u"
#define PRIxFAST32 "I32x"
#define PRIXFAST32 "I32X"
#define PRIo64 "I64o"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
#define PRIoLEAST64 "I64o"
#define PRIuLEAST64 "I64u"
#define PRIxLEAST64 "I64x"
#define PRIXLEAST64 "I64X"
#define PRIoFAST64 "I64o"
#define PRIuFAST64 "I64u"
#define PRIxFAST64 "I64x"
#define PRIXFAST64 "I64X"
#define PRIoMAX "I64o"
#define PRIuMAX "I64u"
#define PRIxMAX "I64x"
#define PRIXMAX "I64X"
#define PRIoPTR "Io"
#define PRIuPTR "Iu"
#define PRIxPTR "Ix"
#define PRIXPTR "IX"
// The fscanf macros for signed integers are:
#define SCNd8 "d"
#define SCNi8 "i"
#define SCNdLEAST8 "d"
#define SCNiLEAST8 "i"
#define SCNdFAST8 "d"
#define SCNiFAST8 "i"
#define SCNd16 "hd"
#define SCNi16 "hi"
#define SCNdLEAST16 "hd"
#define SCNiLEAST16 "hi"
#define SCNdFAST16 "hd"
#define SCNiFAST16 "hi"
#define SCNd32 "ld"
#define SCNi32 "li"
#define SCNdLEAST32 "ld"
#define SCNiLEAST32 "li"
#define SCNdFAST32 "ld"
#define SCNiFAST32 "li"
#define SCNd64 "I64d"
#define SCNi64 "I64i"
#define SCNdLEAST64 "I64d"
#define SCNiLEAST64 "I64i"
#define SCNdFAST64 "I64d"
#define SCNiFAST64 "I64i"
#define SCNdMAX "I64d"
#define SCNiMAX "I64i"
#ifdef _WIN64 // [
# define SCNdPTR "I64d"
# define SCNiPTR "I64i"
#else // _WIN64 ][
# define SCNdPTR "ld"
# define SCNiPTR "li"
#endif // _WIN64 ]
// The fscanf macros for unsigned integers are:
#define SCNo8 "o"
#define SCNu8 "u"
#define SCNx8 "x"
#define SCNX8 "X"
#define SCNoLEAST8 "o"
#define SCNuLEAST8 "u"
#define SCNxLEAST8 "x"
#define SCNXLEAST8 "X"
#define SCNoFAST8 "o"
#define SCNuFAST8 "u"
#define SCNxFAST8 "x"
#define SCNXFAST8 "X"
#define SCNo16 "ho"
#define SCNu16 "hu"
#define SCNx16 "hx"
#define SCNX16 "hX"
#define SCNoLEAST16 "ho"
#define SCNuLEAST16 "hu"
#define SCNxLEAST16 "hx"
#define SCNXLEAST16 "hX"
#define SCNoFAST16 "ho"
#define SCNuFAST16 "hu"
#define SCNxFAST16 "hx"
#define SCNXFAST16 "hX"
#define SCNo32 "lo"
#define SCNu32 "lu"
#define SCNx32 "lx"
#define SCNX32 "lX"
#define SCNoLEAST32 "lo"
#define SCNuLEAST32 "lu"
#define SCNxLEAST32 "lx"
#define SCNXLEAST32 "lX"
#define SCNoFAST32 "lo"
#define SCNuFAST32 "lu"
#define SCNxFAST32 "lx"
#define SCNXFAST32 "lX"
#define SCNo64 "I64o"
#define SCNu64 "I64u"
#define SCNx64 "I64x"
#define SCNX64 "I64X"
#define SCNoLEAST64 "I64o"
#define SCNuLEAST64 "I64u"
#define SCNxLEAST64 "I64x"
#define SCNXLEAST64 "I64X"
#define SCNoFAST64 "I64o"
#define SCNuFAST64 "I64u"
#define SCNxFAST64 "I64x"
#define SCNXFAST64 "I64X"
#define SCNoMAX "I64o"
#define SCNuMAX "I64u"
#define SCNxMAX "I64x"
#define SCNXMAX "I64X"
#ifdef _WIN64 // [
# define SCNoPTR "I64o"
# define SCNuPTR "I64u"
# define SCNxPTR "I64x"
# define SCNXPTR "I64X"
#else // _WIN64 ][
# define SCNoPTR "lo"
# define SCNuPTR "lu"
# define SCNxPTR "lx"
# define SCNXPTR "lX"
#endif // _WIN64 ]
// 7.8.2 Functions for greatest-width integer types
// 7.8.2.1 The imaxabs function
#define imaxabs _abs64
// 7.8.2.2 The imaxdiv function
// This is modified version of div() function from Microsoft's div.c found
// in %MSVC.NET%\crt\src\div.c
#ifdef STATIC_IMAXDIV // [
static
#else // STATIC_IMAXDIV ][
_inline
#endif // STATIC_IMAXDIV ]
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
{
imaxdiv_t result;
result.quot = numer / denom;
result.rem = numer % denom;
if (numer < 0 && result.rem > 0) {
// did division wrong; must fix up
++result.quot;
result.rem -= denom;
}
return result;
}
// 7.8.2.3 The strtoimax and strtoumax functions
#define strtoimax _strtoi64
#define strtoumax _strtoui64
// 7.8.2.4 The wcstoimax and wcstoumax functions
#define wcstoimax _wcstoi64
#define wcstoumax _wcstoui64
#endif // _MSC_INTTYPES_H_ ]

45
cmake/msvc/stdbool.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2005, 2006 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef STDBOOL_WIN32_H
#define STDBOOL_WIN32_H
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef __cplusplus
typedef unsigned char bool;
#define true 1
#define false 0
#ifndef CASSERT
#define CASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
#endif
CASSERT(sizeof(bool) == 1, bool_is_one_byte)
CASSERT(true, true_is_true)
CASSERT(!false, false_is_false)
#endif
#endif

251
cmake/msvc/stdint.h Normal file
View File

@ -0,0 +1,251 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#ifndef INTMAX_C
#define INTMAX_C INT64_C
#endif
#ifndef UINTMAX_C
#define UINTMAX_C UINT64_C
#endif
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]

69
cmake/msvc/sys/time.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_SYS_TIME_H_
#define _MSC_SYS_TIME_H_
//http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/430449b3-f6dd-4e18-84de-eebd26a8d668
#include < time.h >
#include <windows.h> //I've ommited this line.
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
struct timespec {
time_t tv_sec; /* Seconds since 00:00:00 GMT, */
/* 1 January 1970 */
long tv_nsec; /* Additional nanoseconds since */
/* tv_sec */
};
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
static inline int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
#endif //_MSC_SYS_TIME_H_

10
cmake/msvc/unistd.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_UNISTD_H_ // [
#define _MSC_UNISTD_H_
#include <process.h>
#endif // _MSC_UNISTD_H_ ]

View File

@ -1,14 +1,14 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/@GR_LIBRARY_DIR@
includedir=${prefix}/@GR_INCLUDE_DIR@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @CPACK_PACKAGE_NAME@
Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@
URL: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
Version: @CPACK_PACKAGE_VERSION@
Requires: gnuradio-runtime gnuradio-blocks
Requires.private: @GR_OSMOSDR_PC_REQUIRES@
Requires: @GR_OSMOSDR_PC_REQUIRES@
Requires.private:
Conflicts:
Cflags: -I${includedir} @GR_OSMOSDR_PC_CFLAGS@
Libs: -L${libdir} -lgnuradio-osmosdr

View File

@ -0,0 +1,78 @@
# Copyright 2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
# Install public header files
########################################################################
install(FILES
gnuradio/blocks/api.h
gnuradio/blocks/null_sink.h
gnuradio/blocks/null_source.h
gnuradio/blocks/throttle.h
DESTINATION include/osmosdr/runtime/gnuradio/blocks
)
install(FILES
gnuradio/thread/thread.h
gnuradio/thread/thread_body_wrapper.h
gnuradio/thread/thread_group.h
DESTINATION include/osmosdr/runtime/gnuradio/thread
)
install(FILES
gnuradio/api.h
gnuradio/attributes.h
gnuradio/basic_block.h
gnuradio/block.h
gnuradio/block_detail.h
gnuradio/block_gateway.h
gnuradio/block_registry.h
gnuradio/buffer.h
gnuradio/constants.h
gnuradio/endianness.h
gnuradio/expj.h
gnuradio/feval.h
gnuradio/flowgraph.h
gnuradio/fxpt.h
gnuradio/fxpt_nco.h
gnuradio/fxpt_vco.h
gnuradio/gr_complex.h
gnuradio/hier_block2.h
gnuradio/high_res_timer.h
gnuradio/io_signature.h
gnuradio/logger.h
gnuradio/math.h
gnuradio/misc.h
gnuradio/prefs.h
gnuradio/random.h
gnuradio/realtime.h
gnuradio/realtime_impl.h
gnuradio/runtime_types.h
gnuradio/sincos.h
gnuradio/sptr_magic.h
gnuradio/sync_block.h
gnuradio/sync_decimator.h
gnuradio/sync_interpolator.h
gnuradio/sys_paths.h
gnuradio/top_block.h
gnuradio/tpb_detail.h
gnuradio/types.h
DESTINATION include/osmosdr/runtime/gnuradio
)

View File

@ -0,0 +1,33 @@
/*
* Copyright 2010-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_RUNTIME_API_H
#define INCLUDED_GR_RUNTIME_RUNTIME_API_H
#include <gnuradio/attributes.h>
#ifdef gnuradio_runtime_EXPORTS
# define GR_RUNTIME_API __GR_ATTR_EXPORT
#else
# define GR_RUNTIME_API __GR_ATTR_IMPORT
#endif
#endif /* INCLUDED_GR_RUNTIME_RUNTIME_API_H */

View File

@ -0,0 +1,74 @@
/*
* Copyright 2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GNURADIO_ATTRIBUTES_H
#define INCLUDED_GNURADIO_ATTRIBUTES_H
////////////////////////////////////////////////////////////////////////
// Cross-platform attribute macros
////////////////////////////////////////////////////////////////////////
#if defined __GNUC__
# define __GR_ATTR_ALIGNED(x) __attribute__((aligned(x)))
# define __GR_ATTR_UNUSED __attribute__((unused))
# define __GR_ATTR_INLINE __attribute__((always_inline))
# define __GR_ATTR_DEPRECATED __attribute__((deprecated))
# if __GNUC__ >= 4
# define __GR_ATTR_EXPORT __attribute__((visibility("default")))
# define __GR_ATTR_IMPORT __attribute__((visibility("default")))
# else
# define __GR_ATTR_EXPORT
# define __GR_ATTR_IMPORT
# endif
#elif _MSC_VER
# define __GR_ATTR_ALIGNED(x) __declspec(align(x))
# define __GR_ATTR_UNUSED
# define __GR_ATTR_INLINE __forceinline
# define __GR_ATTR_DEPRECATED __declspec(deprecated)
# define __GR_ATTR_EXPORT __declspec(dllexport)
# define __GR_ATTR_IMPORT __declspec(dllimport)
#else
# define __GR_ATTR_ALIGNED(x)
# define __GR_ATTR_UNUSED
# define __GR_ATTR_INLINE
# define __GR_ATTR_DEPRECATED
# define __GR_ATTR_EXPORT
# define __GR_ATTR_IMPORT
#endif
////////////////////////////////////////////////////////////////////////
// define inline when building C
////////////////////////////////////////////////////////////////////////
#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline)
# define inline __inline
#endif
////////////////////////////////////////////////////////////////////////
// suppress warnings
////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data
# pragma warning(disable: 4305) // 'initializing' : truncation from 'double' to 'float'
# pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
#endif
#endif /* INCLUDED_GNURADIO_ATTRIBUTES_H */

View File

@ -0,0 +1,209 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2008,2009,2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_BASIC_BLOCK_H
#define INCLUDED_GR_BASIC_BLOCK_H
#include <gnuradio/api.h>
#include <gnuradio/sptr_magic.h>
#include <gnuradio/runtime_types.h>
#include <gnuradio/io_signature.h>
#include <gnuradio/thread/thread.h>
#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include <boost/foreach.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/any.hpp>
#include <iostream>
#include <string>
#include <deque>
#include <map>
#ifdef GR_CTRLPORT
#include <gnuradio/rpcregisterhelpers.h>
#endif
namespace gr {
/*!
* \brief The abstract base class for all signal processing blocks.
* \ingroup internal
*
* Basic blocks are the bare abstraction of an entity that has a
* name, a set of inputs and outputs, and a message queue. These
* are never instantiated directly; rather, this is the abstract
* parent class of both gr_hier_block, which is a recursive
* container, and block, which implements actual signal
* processing functions.
*/
class GR_RUNTIME_API basic_block : public boost::enable_shared_from_this<basic_block>
{
private:
gr::thread::mutex mutex; //< protects all vars
protected:
friend class flowgraph;
friend class flat_flowgraph; // TODO: will be redundant
friend class tpb_thread_body;
enum vcolor { WHITE, GREY, BLACK };
std::string d_name;
gr::io_signature::sptr d_input_signature;
gr::io_signature::sptr d_output_signature;
long d_unique_id;
long d_symbolic_id;
std::string d_symbol_name;
std::string d_symbol_alias;
vcolor d_color;
bool d_rpc_set;
std::vector<boost::any> d_rpc_vars; // container for all RPC variables
basic_block(void) {} // allows pure virtual interface sub-classes
//! Protected constructor prevents instantiation by non-derived classes
basic_block(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
//! may only be called during constructor
void set_input_signature(gr::io_signature::sptr iosig) {
d_input_signature = iosig;
}
//! may only be called during constructor
void set_output_signature(gr::io_signature::sptr iosig) {
d_output_signature = iosig;
}
/*!
* \brief Allow the flowgraph to set for sorting and partitioning
*/
void set_color(vcolor color) { d_color = color; }
vcolor color() const { return d_color; }
public:
virtual ~basic_block();
long unique_id() const { return d_unique_id; }
long symbolic_id() const { return d_symbolic_id; }
std::string name() const { return d_name; }
std::string symbol_name() const { return d_symbol_name; }
gr::io_signature::sptr input_signature() const { return d_input_signature; }
gr::io_signature::sptr output_signature() const { return d_output_signature; }
basic_block_sptr to_basic_block(); // Needed for Python type coercion
bool alias_set() { return !d_symbol_alias.empty(); }
std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
void set_block_alias(std::string name);
#ifdef GR_CTRLPORT
/*!
* \brief Add an RPC variable (get or set).
*
* Using controlport, we create new getters/setters and need to
* store them. Each block has a vector to do this, and these never
* need to be accessed again once they are registered with the RPC
* backend. This function takes a
* boost::shared_sptr<rpcbasic_base> so that when the block is
* deleted, all RPC registered variables are cleaned up.
*
* \param s an rpcbasic_sptr of the new RPC variable register to store.
*/
void add_rpc_variable(rpcbasic_sptr s)
{
d_rpc_vars.push_back(s);
}
#endif /* GR_CTRLPORT */
/*!
* \brief Set up the RPC registered variables.
*
* This must be overloaded by a block that wants to use
* controlport. This is where rpcbasic_register_{get,set} pointers
* are created, which then get wrapped as shared pointers
* (rpcbasic_sptr(...)) and stored using add_rpc_variable.
*/
virtual void setup_rpc() {};
/*!
* \brief Ask if this block has been registered to the RPC.
*
* We can only register a block once, so we use this to protect us
* from calling it multiple times.
*/
bool is_rpc_set() { return d_rpc_set; }
/*!
* \brief When the block is registered with the RPC, set this.
*/
void rpc_set() { d_rpc_set = true; }
/*!
* \brief Confirm that ninputs and noutputs is an acceptable combination.
*
* \param ninputs number of input streams connected
* \param noutputs number of output streams connected
*
* \returns true if this is a valid configuration for this block.
*
* This function is called by the runtime system whenever the
* topology changes. Most classes do not need to override this.
* This check is in addition to the constraints specified by the
* input and output gr::io_signatures.
*/
virtual bool check_topology(int ninputs, int noutputs) {
(void)ninputs;
(void)noutputs;
return true;
}
virtual void set_processor_affinity(const std::vector<int> &mask)
{ throw std::runtime_error("set_processor_affinity not overloaded in child class."); }
virtual void unset_processor_affinity()
{ throw std::runtime_error("unset_processor_affinity not overloaded in child class."); }
virtual std::vector<int> processor_affinity()
{ throw std::runtime_error("processor_affinity not overloaded in child class."); }
};
inline bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
{
return lhs->unique_id() < rhs->unique_id();
}
typedef std::vector<basic_block_sptr> basic_block_vector_t;
typedef std::vector<basic_block_sptr>::iterator basic_block_viter_t;
GR_RUNTIME_API long basic_block_ncurrently_allocated();
inline std::ostream &operator << (std::ostream &os, basic_block_sptr basic_block)
{
os << basic_block->name() << "(" << basic_block->unique_id() << ")";
return os;
}
} /* namespace gr */
#endif /* INCLUDED_GR_BASIC_BLOCK_H */

View File

@ -0,0 +1,573 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2007,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_BLOCK_H
#define INCLUDED_GR_RUNTIME_BLOCK_H
#include <gnuradio/api.h>
#include <gnuradio/basic_block.h>
#include <gnuradio/logger.h>
namespace gr {
/*!
* \brief The abstract base class for all 'terminal' processing blocks.
* \ingroup base_blk
*
* A signal processing flow is constructed by creating a tree of
* hierarchical blocks, which at any level may also contain terminal
* nodes that actually implement signal processing functions. This
* is the base class for all such leaf nodes.
*
* Blocks have a set of input streams and output streams. The
* input_signature and output_signature define the number of input
* streams and output streams respectively, and the type of the data
* items in each stream.
*
* Although blocks may consume data on each input stream at a
* different rate, all outputs streams must produce data at the same
* rate. That rate may be different from any of the input rates.
*
* User derived blocks override two methods, forecast and
* general_work, to implement their signal processing
* behavior. forecast is called by the system scheduler to determine
* how many items are required on each input stream in order to
* produce a given number of output items.
*
* general_work is called to perform the signal processing in the
* block. It reads the input items and writes the output items.
*/
class GR_RUNTIME_API block : public basic_block
{
public:
//! Magic return values from general_work
enum {
WORK_CALLED_PRODUCE = -2,
WORK_DONE = -1
};
enum tag_propagation_policy_t {
TPP_DONT = 0,
TPP_ALL_TO_ALL = 1,
TPP_ONE_TO_ONE = 2
};
virtual ~block();
/*!
* Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...)
* History is the number of x_i's that are examined to produce one y_i.
* This comes in handy for FIR filters, where we use history to
* ensure that our input contains the appropriate "history" for the
* filter. History should be equal to the number of filter taps.
*/
unsigned history() const { return d_history; }
void set_history(unsigned history) { d_history = history; }
/*!
* \brief Return true if this block has a fixed input to output rate.
*
* If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
*/
bool fixed_rate() const { return d_fixed_rate; }
// ----------------------------------------------------------------
// override these to define your behavior
// ----------------------------------------------------------------
/*!
* \brief Estimate input requirements given output request
*
* \param noutput_items number of output items to produce
* \param ninput_items_required number of input items required on each input stream
*
* Given a request to product \p noutput_items, estimate the
* number of data items required on each input stream. The
* estimate doesn't have to be exact, but should be close.
*/
virtual void forecast(int noutput_items,
gr_vector_int &ninput_items_required);
/*!
* \brief compute output items from input items
*
* \param noutput_items number of output items to write on each output stream
* \param ninput_items number of input items available on each input stream
* \param input_items vector of pointers to the input items, one entry per input stream
* \param output_items vector of pointers to the output items, one entry per output stream
*
* \returns number of items actually written to each output stream, or -1 on EOF.
* It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items
*
* general_work must call consume or consume_each to indicate how
* many items were consumed on each input stream.
*/
virtual int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
/*!
* \brief Called to enable drivers, etc for i/o devices.
*
* This allows a block to enable an associated driver to begin
* transfering data just before we start to execute the scheduler.
* The end result is that this reduces latency in the pipeline
* when dealing with audio devices, usrps, etc.
*/
virtual bool start();
/*!
* \brief Called to disable drivers, etc for i/o devices.
*/
virtual bool stop();
// ----------------------------------------------------------------
/*!
* \brief Constrain the noutput_items argument passed to forecast and general_work
*
* set_output_multiple causes the scheduler to ensure that the
* noutput_items argument passed to forecast and general_work will
* be an integer multiple of \param multiple The default value of
* output multiple is 1.
*/
void set_output_multiple(int multiple);
int output_multiple() const { return d_output_multiple; }
bool output_multiple_set() const { return d_output_multiple_set; }
/*!
* \brief Constrains buffers to work on a set item alignment (for SIMD)
*
* set_alignment_multiple causes the scheduler to ensure that the
* noutput_items argument passed to forecast and general_work will
* be an integer multiple of \param multiple The default value is
* 1.
*
* This control is similar to the output_multiple setting, except
* that if the number of items passed to the block is less than
* the output_multiple, this value is ignored and the block can
* produce like normal. The d_unaligned value is set to the number
* of items the block is off by. In the next call to general_work,
* the noutput_items is set to d_unaligned or less until
* d_unaligned==0. The buffers are now aligned again and the
* aligned calls can be performed again.
*/
void set_alignment(int multiple);
int alignment() const { return d_output_multiple; }
void set_unaligned(int na);
int unaligned() const { return d_unaligned; }
void set_is_unaligned(bool u);
bool is_unaligned() const { return d_is_unaligned; }
/*!
* \brief Tell the scheduler \p how_many_items of input stream \p
* which_input were consumed.
*/
void consume(int which_input, int how_many_items);
/*!
* \brief Tell the scheduler \p how_many_items were consumed on
* each input stream.
*/
void consume_each(int how_many_items);
/*!
* \brief Tell the scheduler \p how_many_items were produced on
* output stream \p which_output.
*
* If the block's general_work method calls produce, \p
* general_work must return WORK_CALLED_PRODUCE.
*/
void produce(int which_output, int how_many_items);
/*!
* \brief Set the approximate output rate / input rate
*
* Provide a hint to the buffer allocator and scheduler.
* The default relative_rate is 1.0
*
* decimators have relative_rates < 1.0
* interpolators have relative_rates > 1.0
*/
void set_relative_rate(double relative_rate);
/*!
* \brief return the approximate output rate / input rate
*/
double relative_rate() const { return d_relative_rate; }
/*
* The following two methods provide special case info to the
* scheduler in the event that a block has a fixed input to output
* ratio. sync_block, sync_decimator and
* sync_interpolator override these. If you're fixed rate,
* subclass one of those.
*/
/*!
* \brief Given ninput samples, return number of output samples that will be produced.
* N.B. this is only defined if fixed_rate returns true.
* Generally speaking, you don't need to override this.
*/
virtual int fixed_rate_ninput_to_noutput(int ninput);
/*!
* \brief Given noutput samples, return number of input samples required to produce noutput.
* N.B. this is only defined if fixed_rate returns true.
* Generally speaking, you don't need to override this.
*/
virtual int fixed_rate_noutput_to_ninput(int noutput);
/*!
* \brief Return the number of items read on input stream which_input
*/
uint64_t nitems_read(unsigned int which_input);
/*!
* \brief Return the number of items written on output stream which_output
*/
uint64_t nitems_written(unsigned int which_output);
/*!
* \brief Return the minimum number of output items this block can
* produce during a call to work.
*
* Should be 0 for most blocks. Useful if we're dealing with
* packets and the block produces one packet per call to work.
*/
int min_noutput_items() const { return d_min_noutput_items; }
/*!
* \brief Set the minimum number of output items this block can
* produce during a call to work.
*
* \param m the minimum noutput_items this block can produce.
*/
void set_min_noutput_items(int m) { d_min_noutput_items = m; }
/*!
* \brief Return the maximum number of output items this block will
* handle during a call to work.
*/
int max_noutput_items();
/*!
* \brief Set the maximum number of output items this block will
* handle during a call to work.
*
* \param m the maximum noutput_items this block will handle.
*/
void set_max_noutput_items(int m);
/*!
* \brief Clear the switch for using the max_noutput_items value of this block.
*
* When is_set_max_noutput_items() returns 'true', the scheduler
* will use the value returned by max_noutput_items() to limit the
* size of the number of items possible for this block's work
* function. If is_set_max_notput_items() returns 'false', then
* the scheduler ignores the internal value and uses the value set
* globally in the top_block.
*
* Use this value to clear the 'is_set' flag so the scheduler will
* ignore this. Use the set_max_noutput_items(m) call to both set
* a new value for max_noutput_items and to reenable its use in
* the scheduler.
*/
void unset_max_noutput_items();
/*!
* \brief Ask the block if the flag is or is not set to use the
* internal value of max_noutput_items during a call to work.
*/
bool is_set_max_noutput_items();
/*
* Used to expand the vectors that hold the min/max buffer sizes.
*
* Specifically, when -1 is used, the vectors are just initialized
* with 1 value; this is used by the flat_flowgraph to expand when
* required to add a new value for new ports on these blocks.
*/
void expand_minmax_buffer(int port);
/*!
* \brief Returns max buffer size on output port \p i.
*/
long max_output_buffer(size_t i);
/*!
* \brief Sets max buffer size on all output ports.
*/
void set_max_output_buffer(long max_output_buffer);
/*!
* \brief Sets max buffer size on output port \p port.
*/
void set_max_output_buffer(int port, long max_output_buffer);
/*!
* \brief Returns min buffer size on output port \p i.
*/
long min_output_buffer(size_t i);
/*!
* \brief Sets min buffer size on all output ports.
*/
void set_min_output_buffer(long min_output_buffer);
/*!
* \brief Sets min buffer size on output port \p port.
*/
void set_min_output_buffer(int port, long min_output_buffer);
// --------------- Performance counter functions -------------
/*!
* \brief Gets instantaneous noutput_items performance counter.
*/
float pc_noutput_items();
/*!
* \brief Gets average noutput_items performance counter.
*/
float pc_noutput_items_avg();
/*!
* \brief Gets variance of noutput_items performance counter.
*/
float pc_noutput_items_var();
/*!
* \brief Gets instantaneous num items produced performance counter.
*/
float pc_nproduced();
/*!
* \brief Gets average num items produced performance counter.
*/
float pc_nproduced_avg();
/*!
* \brief Gets variance of num items produced performance counter.
*/
float pc_nproduced_var();
/*!
* \brief Gets instantaneous fullness of \p which input buffer.
*/
float pc_input_buffers_full(int which);
/*!
* \brief Gets average fullness of \p which input buffer.
*/
float pc_input_buffers_full_avg(int which);
/*!
* \brief Gets variance of fullness of \p which input buffer.
*/
float pc_input_buffers_full_var(int which);
/*!
* \brief Gets instantaneous fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full();
/*!
* \brief Gets average fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full_avg();
/*!
* \brief Gets variance of fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full_var();
/*!
* \brief Gets instantaneous fullness of \p which input buffer.
*/
float pc_output_buffers_full(int which);
/*!
* \brief Gets average fullness of \p which input buffer.
*/
float pc_output_buffers_full_avg(int which);
/*!
* \brief Gets variance of fullness of \p which input buffer.
*/
float pc_output_buffers_full_var(int which);
/*!
* \brief Gets instantaneous fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full();
/*!
* \brief Gets average fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full_avg();
/*!
* \brief Gets variance of fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full_var();
/*!
* \brief Gets instantaneous clock cycles spent in work.
*/
float pc_work_time();
/*!
* \brief Gets average clock cycles spent in work.
*/
float pc_work_time_avg();
/*!
* \brief Gets average clock cycles spent in work.
*/
float pc_work_time_var();
/*!
* \brief Resets the performance counters
*/
void reset_perf_counters();
/*!
* \brief Sets up export of perf. counters to ControlPort. Only
* called by the scheduler.
*/
void setup_pc_rpc();
/*!
* \brief Checks if this block is already exporting perf. counters
* to ControlPort.
*/
bool is_pc_rpc_set() { return d_pc_rpc_set; }
/*!
* \brief If the block calls this in its constructor, it's
* perf. counters will not be exported.
*/
void no_pc_rpc() { d_pc_rpc_set = true; }
// ----------------------------------------------------------------------------
// Functions to handle thread affinity
/*!
* \brief Set the thread's affinity to processor core \p n.
*
* \param mask a vector of ints of the core numbers available to this block.
*/
void set_processor_affinity(const std::vector<int> &mask);
/*!
* \brief Remove processor affinity to a specific core.
*/
void unset_processor_affinity();
/*!
* \brief Get the current processor affinity.
*/
std::vector<int> processor_affinity() { return d_affinity; }
/*!
* \brief Get the current thread priority in use
*/
int active_thread_priority();
/*!
* \brief Get the current thread priority stored
*/
int thread_priority();
/*!
* \brief Set the current thread priority
*/
int set_thread_priority(int priority);
// ----------------------------------------------------------------------------
private:
int d_output_multiple;
bool d_output_multiple_set;
int d_unaligned;
bool d_is_unaligned;
double d_relative_rate; // approx output_rate / input_rate
block_detail_sptr d_detail; // implementation details
unsigned d_history;
bool d_fixed_rate;
bool d_max_noutput_items_set; // if d_max_noutput_items is valid
int d_max_noutput_items; // value of max_noutput_items for this block
int d_min_noutput_items;
std::vector<int> d_affinity; // thread affinity proc. mask
int d_priority; // thread priority level
bool d_pc_rpc_set;
protected:
block(void) {} // allows pure virtual interface sub-classes
block(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
void set_fixed_rate(bool fixed_rate) { d_fixed_rate = fixed_rate; }
std::vector<long> d_max_output_buffer;
std::vector<long> d_min_output_buffer;
/*! Used by block's setters and work functions to make
* setting/resetting of parameters thread-safe.
*
* Used by calling gr::thread::scoped_lock l(d_setlock);
*/
gr::thread::mutex d_setlock;
/*! Used by blocks to access the logger system.
*/
gr::logger_ptr d_logger;
gr::logger_ptr d_debug_logger;
// These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friend GR_RUNTIME_APIs
public:
block_detail_sptr detail() const { return d_detail; }
void set_detail(block_detail_sptr detail) { d_detail = detail; }
};
typedef std::vector<block_sptr> block_vector_t;
typedef std::vector<block_sptr>::iterator block_viter_t;
inline block_sptr cast_to_block_sptr(basic_block_sptr p)
{
return boost::dynamic_pointer_cast<block, basic_block>(p);
}
std::ostream&
operator << (std::ostream& os, const block *m);
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BLOCK_H */

View File

@ -0,0 +1,207 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more detail.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H
#define INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H
#include <gnuradio/api.h>
#include <gnuradio/runtime_types.h>
#include <gnuradio/tpb_detail.h>
#include <gnuradio/high_res_timer.h>
#include <stdexcept>
namespace gr {
/*!
* \brief Implementation details to support the signal processing abstraction
* \ingroup internal
*
* This class contains implementation detail that should be "out of
* sight" of almost all users of GNU Radio. This decoupling also
* means that we can make changes to the guts without having to
* recompile everything.
*/
class GR_RUNTIME_API block_detail
{
public:
~block_detail();
int ninputs() const { return d_ninputs; }
int noutputs() const { return d_noutputs; }
bool sink_p() const { return d_noutputs == 0; }
bool source_p() const { return d_ninputs == 0; }
void set_done(bool done);
bool done() const { return d_done; }
void set_input(unsigned int which, buffer_reader_sptr reader);
buffer_reader_sptr input(unsigned int which)
{
if(which >= d_ninputs)
throw std::invalid_argument("block_detail::input");
return d_input[which];
}
void set_output(unsigned int which, buffer_sptr buffer);
buffer_sptr output(unsigned int which)
{
if(which >= d_noutputs)
throw std::invalid_argument("block_detail::output");
return d_output[which];
}
/*!
* \brief Tell the scheduler \p how_many_items of input stream \p
* which_input were consumed.
*/
void consume(int which_input, int how_many_items);
/*!
* \brief Tell the scheduler \p how_many_items were consumed on
* each input stream.
*/
void consume_each(int how_many_items);
/*!
* \brief Tell the scheduler \p how_many_items were produced on
* output stream \p which_output.
*/
void produce(int which_output, int how_many_items);
/*!
* \brief Tell the scheduler \p how_many_items were produced on
* each output stream.
*/
void produce_each(int how_many_items);
// Return the number of items read on input stream which_input
uint64_t nitems_read(unsigned int which_input);
// Return the number of items written on output stream which_output
uint64_t nitems_written(unsigned int which_output);
/*!
* \brief Set core affinity of block to the cores in the vector
* mask.
*
* \param mask a vector of ints of the core numbers available to
* this block.
*/
void set_processor_affinity(const std::vector<int> &mask);
/*!
* \brief Unset core affinity.
*/
void unset_processor_affinity();
/*!
* \brief Get the current thread priority
*/
int thread_priority();
/*!
* \brief Set the current thread priority
*
* \param priority the new thread priority to set
*/
int set_thread_priority(int priority);
bool threaded; // set if thread is currently running.
gr::thread::gr_thread_t thread; // portable thread handle
void start_perf_counters();
void stop_perf_counters(int noutput_items, int nproduced);
void reset_perf_counters();
// Calls to get performance counter items
float pc_noutput_items();
float pc_nproduced();
float pc_input_buffers_full(size_t which);
std::vector<float> pc_input_buffers_full();
float pc_output_buffers_full(size_t which);
std::vector<float> pc_output_buffers_full();
float pc_work_time();
float pc_noutput_items_avg();
float pc_nproduced_avg();
float pc_input_buffers_full_avg(size_t which);
std::vector<float> pc_input_buffers_full_avg();
float pc_output_buffers_full_avg(size_t which);
std::vector<float> pc_output_buffers_full_avg();
float pc_work_time_avg();
float pc_noutput_items_var();
float pc_nproduced_var();
float pc_input_buffers_full_var(size_t which);
std::vector<float> pc_input_buffers_full_var();
float pc_output_buffers_full_var(size_t which);
std::vector<float> pc_output_buffers_full_var();
float pc_work_time_var();
tpb_detail d_tpb; // used by thread-per-block scheduler
int d_produce_or;
// ----------------------------------------------------------------------------
private:
unsigned int d_ninputs;
unsigned int d_noutputs;
std::vector<buffer_reader_sptr> d_input;
std::vector<buffer_sptr> d_output;
bool d_done;
// Performance counters
float d_ins_noutput_items;
float d_avg_noutput_items;
float d_var_noutput_items;
float d_ins_nproduced;
float d_avg_nproduced;
float d_var_nproduced;
std::vector<float> d_ins_input_buffers_full;
std::vector<float> d_avg_input_buffers_full;
std::vector<float> d_var_input_buffers_full;
std::vector<float> d_ins_output_buffers_full;
std::vector<float> d_avg_output_buffers_full;
std::vector<float> d_var_output_buffers_full;
gr::high_res_timer_type d_start_of_work, d_end_of_work;
float d_ins_work_time;
float d_avg_work_time;
float d_var_work_time;
float d_pc_counter;
block_detail(unsigned int ninputs, unsigned int noutputs);
friend struct tpb_detail;
friend GR_RUNTIME_API block_detail_sptr
make_block_detail(unsigned int ninputs, unsigned int noutputs);
};
GR_RUNTIME_API block_detail_sptr
make_block_detail(unsigned int ninputs, unsigned int noutputs);
GR_RUNTIME_API long
block_detail_ncurrently_allocated();
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H */

View File

@ -0,0 +1,178 @@
/* -*- c++ -*- */
/*
* Copyright 2011-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_H
#define INCLUDED_RUNTIME_BLOCK_GATEWAY_H
#include <gnuradio/api.h>
#include <gnuradio/block.h>
#include <gnuradio/feval.h>
namespace gr {
/*!
* The work type enum tells the gateway what kind of block to
* implement. The choices are familiar gnuradio block overloads
* (sync, decim, interp).
*/
enum block_gw_work_type {
GR_BLOCK_GW_WORK_GENERAL,
GR_BLOCK_GW_WORK_SYNC,
GR_BLOCK_GW_WORK_DECIM,
GR_BLOCK_GW_WORK_INTERP,
};
/*!
* Shared message structure between python and gateway.
* Each action type represents a scheduler-called function.
*/
struct block_gw_message_type {
enum action_type {
ACTION_GENERAL_WORK, //dispatch work
ACTION_WORK, //dispatch work
ACTION_FORECAST, //dispatch forecast
ACTION_START, //dispatch start
ACTION_STOP, //dispatch stop
};
action_type action;
int general_work_args_noutput_items;
std::vector<int> general_work_args_ninput_items;
std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
std::vector<void *> general_work_args_output_items;
int general_work_args_return_value;
int work_args_ninput_items;
int work_args_noutput_items;
std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
std::vector<void *> work_args_output_items;
int work_args_return_value;
int forecast_args_noutput_items;
std::vector<int> forecast_args_ninput_items_required;
bool start_args_return_value;
bool stop_args_return_value;
};
/*!
* The gateway block which performs all the magic.
*
* The gateway provides access to all the gr::block routines.
* The methods prefixed with gr::block__ are renamed
* to class methods without the prefix in python.
*/
class GR_RUNTIME_API block_gateway : virtual public gr::block
{
public:
// gr::block_gateway::sptr
typedef boost::shared_ptr<block_gateway> sptr;
/*!
* Make a new gateway block.
* \param handler the swig director object with callback
* \param name the name of the block (Ex: "Shirley")
* \param in_sig the input signature for this block
* \param out_sig the output signature for this block
* \param work_type the type of block overload to implement
* \param factor the decimation or interpolation factor
* \return a new gateway block
*/
static sptr make(gr::feval_ll *handler,
const std::string &name,
gr::io_signature::sptr in_sig,
gr::io_signature::sptr out_sig,
const block_gw_work_type work_type,
const unsigned factor);
//! Provide access to the shared message object
virtual block_gw_message_type &block_message(void) = 0;
long block__unique_id(void) const {
return gr::block::unique_id();
}
std::string block__name(void) const {
return gr::block::name();
}
unsigned block__history(void) const {
return gr::block::history();
}
void block__set_history(unsigned history) {
return gr::block::set_history(history);
}
void block__set_fixed_rate(bool fixed_rate) {
return gr::block::set_fixed_rate(fixed_rate);
}
bool block__fixed_rate(void) const {
return gr::block::fixed_rate();
}
void block__set_output_multiple(int multiple) {
return gr::block::set_output_multiple(multiple);
}
int block__output_multiple(void) const {
return gr::block::output_multiple();
}
void block__consume(int which_input, int how_many_items) {
return gr::block::consume(which_input, how_many_items);
}
void block__consume_each(int how_many_items) {
return gr::block::consume_each(how_many_items);
}
void block__produce(int which_output, int how_many_items) {
return gr::block::produce(which_output, how_many_items);
}
void block__set_relative_rate(double relative_rate) {
return gr::block::set_relative_rate(relative_rate);
}
double block__relative_rate(void) const {
return gr::block::relative_rate();
}
uint64_t block__nitems_read(unsigned int which_input) {
return gr::block::nitems_read(which_input);
}
uint64_t block__nitems_written(unsigned int which_output) {
return gr::block::nitems_written(which_output);
}
protected:
};
} /* namespace gr */
#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */

View File

@ -0,0 +1,66 @@
/* -*- c++ -*- */
/*
* Copyright 2012-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef GR_RUNTIME_BLOCK_REGISTRY_H
#define GR_RUNTIME_BLOCK_REGISTRY_H
#include <gnuradio/api.h>
#include <gnuradio/basic_block.h>
#include <map>
namespace gr {
#ifndef GR_BASIC_BLOCK_H
class basic_block;
class block;
#endif
class GR_RUNTIME_API block_registry
{
public:
block_registry();
long block_register(basic_block* block);
void block_unregister(basic_block* block);
std::string register_symbolic_name(basic_block* block);
void register_symbolic_name(basic_block* block, std::string name);
void register_primitive(std::string blk, gr::block* ref);
void unregister_primitive(std::string blk);
void notify_blk(std::string blk);
private:
//typedef std::map< long, basic_block_sptr > blocksubmap_t;
typedef std::map< long, basic_block* > blocksubmap_t;
typedef std::map< std::string, blocksubmap_t > blockmap_t;
blockmap_t d_map;
std::map< std::string, block*> primitive_map;
gr::thread::mutex d_mutex;
};
} /* namespace gr */
GR_RUNTIME_API extern gr::block_registry global_block_registry;
#endif /* GR_RUNTIME_BLOCK_REGISTRY_H */

View File

@ -0,0 +1,33 @@
/*
* Copyright 2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLOCKS_API_H
#define INCLUDED_BLOCKS_API_H
#include <gnuradio/attributes.h>
#ifdef gnuradio_blocks_EXPORTS
# define BLOCKS_API __GR_ATTR_EXPORT
#else
# define BLOCKS_API __GR_ATTR_IMPORT
#endif
#endif /* INCLUDED_BLOCKS_API_H */

View File

@ -0,0 +1,55 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_NULL_SINK_H
#define INCLUDED_GR_NULL_SINK_H
#include <gnuradio/blocks/api.h>
#include <gnuradio/sync_block.h>
#include <stddef.h> // size_t
namespace gr {
namespace blocks {
/*!
* \brief Bit bucket. Use as a termination point when a sink is
* required and we don't want to do anything real.
* \ingroup misc_blk
*/
class BLOCKS_API null_sink : virtual public sync_block
{
public:
// gr::blocks::null_sink::sptr
typedef boost::shared_ptr<null_sink> sptr;
/*!
* Build a null sink block.
*
* \param sizeof_stream_item size of the stream items in bytes.
*/
static sptr make(size_t sizeof_stream_item);
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_NULL_SINK_H */

View File

@ -0,0 +1,53 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_NULL_SOURCE_H
#define INCLUDED_GR_NULL_SOURCE_H
#include <gnuradio/blocks/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
namespace blocks {
/*!
* \brief A source of zeros used mainly for testing.
* \ingroup misc_blk
*/
class BLOCKS_API null_source : virtual public sync_block
{
public:
// gr::blocks::null_source::sptr
typedef boost::shared_ptr<null_source> sptr;
/*!
* Build a null source block.
*
* \param sizeof_stream_item size of the stream items in bytes.
*/
static sptr make(size_t sizeof_stream_item);
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_NULL_SOURCE_H */

View File

@ -0,0 +1,63 @@
/* -*- c++ -*- */
/*
* Copyright 2005-2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_THROTTLE_H
#define INCLUDED_GR_THROTTLE_H
#include <gnuradio/blocks/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
namespace blocks {
/*!
* \brief throttle flow of samples such that the average rate does
* not exceed samples_per_sec.
* \ingroup misc_blk
*
* \details
* input: one stream of itemsize; output: one stream of itemsize
*
* N.B. this should only be used in GUI apps where there is no
* other rate limiting block. It is not intended nor effective at
* precisely controlling the rate of samples. That should be
* controlled by a source or sink tied to sample clock. E.g., a
* USRP or audio card.
*/
class BLOCKS_API throttle : virtual public sync_block
{
public:
typedef boost::shared_ptr<throttle> sptr;
static sptr make(size_t itemsize, double samples_per_sec);
//! Sets the sample rate in samples per second.
virtual void set_sample_rate(double rate) = 0;
//! Get the sample rate in samples per second.
virtual double sample_rate() const = 0;
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_THROTTLE_H */

View File

@ -0,0 +1,258 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2009-2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_BUFFER_H
#define INCLUDED_GR_RUNTIME_BUFFER_H
#include <gnuradio/api.h>
#include <gnuradio/runtime_types.h>
#include <boost/weak_ptr.hpp>
#include <gnuradio/thread/thread.h>
#include <deque>
namespace gr {
class vmcircbuf;
/*!
* \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
*
* The total size of the buffer will be rounded up to a system
* dependent boundary. This is typically the system page size, but
* under MS windows is 64KB.
*
* \param nitems is the minimum number of items the buffer will hold.
* \param sizeof_item is the size of an item in bytes.
* \param link is the block that writes to this buffer.
*/
GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item,
block_sptr link=block_sptr());
/*!
* \brief Single writer, multiple reader fifo.
* \ingroup internal
*/
class GR_RUNTIME_API buffer
{
public:
virtual ~buffer();
/*!
* \brief return number of items worth of space available for writing
*/
int space_available();
/*!
* \brief return size of this buffer in items
*/
int bufsize() const { return d_bufsize; }
/*!
* \brief return pointer to write buffer.
*
* The return value points at space that can hold at least
* space_available() items.
*/
void *write_pointer();
/*!
* \brief tell buffer that we wrote \p nitems into it
*/
void update_write_pointer(int nitems);
void set_done(bool done);
bool done() const { return d_done; }
/*!
* \brief Return the block that writes to this buffer.
*/
block_sptr link() { return block_sptr(d_link); }
size_t nreaders() const { return d_readers.size(); }
buffer_reader* reader(size_t index) { return d_readers[index]; }
gr::thread::mutex *mutex() { return &d_mutex; }
uint64_t nitems_written() { return d_abs_write_offset; }
size_t get_sizeof_item() { return d_sizeof_item; }
// -------------------------------------------------------------------------
private:
friend class buffer_reader;
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link);
friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link);
protected:
char *d_base; // base address of buffer
unsigned int d_bufsize; // in items
private:
gr::vmcircbuf *d_vmcircbuf;
size_t d_sizeof_item; // in bytes
std::vector<buffer_reader *> d_readers;
boost::weak_ptr<block> d_link; // block that writes to this buffer
//
// The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
// and the d_read_index's and d_abs_read_offset's in the buffer readers.
//
gr::thread::mutex d_mutex;
unsigned int d_write_index; // in items [0,d_bufsize)
uint64_t d_abs_write_offset; // num items written since the start
bool d_done;
uint64_t d_last_min_items_read;
unsigned index_add(unsigned a, unsigned b)
{
unsigned s = a + b;
if(s >= d_bufsize)
s -= d_bufsize;
assert(s < d_bufsize);
return s;
}
unsigned index_sub(unsigned a, unsigned b)
{
int s = a - b;
if(s < 0)
s += d_bufsize;
assert((unsigned) s < d_bufsize);
return s;
}
virtual bool allocate_buffer(int nitems, size_t sizeof_item);
/*!
* \brief constructor is private. Use gr_make_buffer to create instances.
*
* Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
*
* \param nitems is the minimum number of items the buffer will hold.
* \param sizeof_item is the size of an item in bytes.
* \param link is the block that writes to this buffer.
*
* The total size of the buffer will be rounded up to a system
* dependent boundary. This is typically the system page size, but
* under MS windows is 64KB.
*/
buffer(int nitems, size_t sizeof_item, block_sptr link);
/*!
* \brief disassociate \p reader from this buffer
*/
void drop_reader(buffer_reader *reader);
};
/*!
* \brief Create a new gr::buffer_reader and attach it to buffer \p buf
* \param buf is the buffer the \p gr::buffer_reader reads from.
* \param nzero_preload -- number of zero items to "preload" into buffer.
* \param link is the block that reads from the buffer using this gr::buffer_reader.
*/
GR_RUNTIME_API buffer_reader_sptr
buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link=block_sptr());
//! returns # of buffers currently allocated
GR_RUNTIME_API long buffer_ncurrently_allocated();
// ---------------------------------------------------------------------------
/*!
* \brief How we keep track of the readers of a gr::buffer.
* \ingroup internal
*/
class GR_RUNTIME_API buffer_reader
{
public:
~buffer_reader();
/*!
* \brief Return number of items available for reading.
*/
int items_available() const;
/*!
* \brief Return buffer this reader reads from.
*/
buffer_sptr buffer() const { return d_buffer; }
/*!
* \brief Return maximum number of items that could ever be available for reading.
* This is used as a sanity check in the scheduler to avoid looping forever.
*/
int max_possible_items_available() const { return d_buffer->d_bufsize - 1; }
/*!
* \brief return pointer to read buffer.
*
* The return value points to items_available() number of items
*/
const void *read_pointer();
/*
* \brief tell buffer we read \p items from it
*/
void update_read_pointer(int nitems);
void set_done(bool done) { d_buffer->set_done(done); }
bool done() const { return d_buffer->done(); }
gr::thread::mutex *mutex() { return d_buffer->mutex(); }
uint64_t nitems_read() { return d_abs_read_offset; }
size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); }
/*!
* \brief Return the block that reads via this reader.
*
*/
block_sptr link() { return block_sptr(d_link); }
// -------------------------------------------------------------------------
private:
friend class buffer;
friend GR_RUNTIME_API buffer_reader_sptr
buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link);
buffer_sptr d_buffer;
unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
uint64_t d_abs_read_offset; // num items seen since the start
boost::weak_ptr<block> d_link; // block that reads via this buffer reader
//! constructor is private. Use gr::buffer::add_reader to create instances
buffer_reader(buffer_sptr buffer, unsigned int read_index, block_sptr link);
};
//! returns # of buffer_readers currently allocated
GR_RUNTIME_API long buffer_reader_ncurrently_allocated ();
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BUFFER_H */

View File

@ -0,0 +1,58 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_CONSTANTS_H
#define INCLUDED_GR_CONSTANTS_H
#include <gnuradio/api.h>
#include <string>
namespace gr {
/*!
* \brief return SYSCONFDIR. Typically ${CMAKE_INSTALL_PREFIX}/etc or /etc
*/
GR_RUNTIME_API const std::string prefix();
/*!
* \brief return SYSCONFDIR. Typically ${CMAKE_INSTALL_PREFIX}/etc or /etc
*/
GR_RUNTIME_API const std::string sysconfdir();
/*!
* \brief return preferences file directory. Typically ${SYSCONFDIR}/etc/conf.d
*/
GR_RUNTIME_API const std::string prefsdir();
/*!
* \brief return date/time of build, as set when 'cmake' is run
*/
GR_RUNTIME_API const std::string build_date();
/*!
* \brief return version string defined by cmake (GrVersion.cmake)
*/
GR_RUNTIME_API const std::string version();
} /* namespace gr */
#endif /* INCLUDED_GR_CONSTANTS_H */

View File

@ -0,0 +1,32 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_ENDIANNESS_H
#define INCLUDED_GR_ENDIANNESS_H
namespace gr {
typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} endianness_t;
} /* namespace gr */
#endif /* INCLUDED_GR_ENDIANNESS_H */

View File

@ -0,0 +1,38 @@
/* -*- c++ -*- */
/*
* Copyright 2006 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_EXPJ_H
#define INCLUDED_GR_EXPJ_H
#include <gnuradio/api.h>
#include <gnuradio/sincos.h>
#include <gnuradio/types.h>
static inline gr_complex
gr_expj(float phase)
{
float t_imag, t_real;
gr::sincosf(phase, &t_imag, &t_real);
return gr_complex(t_real, t_imag);
}
#endif /* INCLUDED_GR_EXPJ_H */

View File

@ -0,0 +1,186 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_FEVAL_H
#define INCLUDED_GR_FEVAL_H
#include <gnuradio/api.h>
#include <gnuradio/gr_complex.h>
namespace gr {
/*!
* \brief base class for evaluating a function: double -> double
* \ingroup misc
*
* This class is designed to be subclassed in Python or C++ and is
* callable from both places. It uses SWIG's "director" feature to
* implement the magic.
*
* It's slow. Don't use it in a performance critical path.
*
* Override eval to define the behavior.
* Use calleval to invoke eval (this kludge is required to allow a
* python specific "shim" to be inserted.
*/
class GR_RUNTIME_API feval_dd
{
protected:
/*!
* \brief override this to define the function
*/
virtual double eval(double x);
public:
feval_dd() {}
virtual ~feval_dd();
virtual double calleval(double x); // invoke "eval"
};
/*!
* \brief base class for evaluating a function: complex -> complex
* \ingroup misc
*
* This class is designed to be subclassed in Python or C++ and is
* callable from both places. It uses SWIG's "director" feature to
* implement the magic.
*
* It's slow. Don't use it in a performance critical path.
*
* Override eval to define the behavior.
* Use calleval to invoke eval (this kludge is required to allow a
* python specific "shim" to be inserted.
*/
class GR_RUNTIME_API feval_cc
{
protected:
/*!
* \brief override this to define the function
*/
virtual gr_complex eval(gr_complex x);
public:
feval_cc() {}
virtual ~feval_cc();
virtual gr_complex calleval(gr_complex x); // invoke "eval"
};
/*!
* \brief base class for evaluating a function: long -> long
* \ingroup misc
*
* This class is designed to be subclassed in Python or C++ and is
* callable from both places. It uses SWIG's "director" feature to
* implement the magic.
*
* It's slow. Don't use it in a performance critical path.
*
* Override eval to define the behavior.
* Use calleval to invoke eval (this kludge is required to allow a
* python specific "shim" to be inserted.
*/
class GR_RUNTIME_API feval_ll
{
protected:
/*!
* \brief override this to define the function
*/
virtual long eval(long x);
public:
feval_ll() {}
virtual ~feval_ll();
virtual long calleval(long x); // invoke "eval"
};
/*!
* \brief base class for evaluating a function: void -> void
* \ingroup misc
*
* This class is designed to be subclassed in Python or C++ and is
* callable from both places. It uses SWIG's "director" feature to
* implement the magic.
*
* It's slow. Don't use it in a performance critical path.
*
* Override eval to define the behavior.
* Use calleval to invoke eval (this kludge is required to allow a
* python specific "shim" to be inserted.
*/
class GR_RUNTIME_API feval
{
protected:
/*!
* \brief override this to define the function
*/
virtual void eval();
public:
feval() {}
virtual ~feval();
virtual void calleval(); // invoke "eval"
};
/*!
* \brief base class for evaluating a function: pmt -> void
* \ingroup misc
*
* This class is designed to be subclassed in Python or C++ and is
* callable from both places. It uses SWIG's "director" feature to
* implement the magic.
*
* It's slow. Don't use it in a performance critical path.
*
* Override eval to define the behavior.
* Use calleval to invoke eval (this kludge is required to allow a
* python specific "shim" to be inserted.
*/
class GR_RUNTIME_API feval_p
{
protected:
/*!
* \brief override this to define the function
*/
virtual void eval(double);
public:
feval_p() {}
virtual ~feval_p();
virtual void calleval(double); // invoke "eval"
};
/*!
* \brief trivial examples / test cases showing C++ calling Python code
*/
GR_RUNTIME_API double feval_dd_example(feval_dd *f, double x);
GR_RUNTIME_API gr_complex feval_cc_example(feval_cc *f, gr_complex x);
GR_RUNTIME_API long feval_ll_example(feval_ll *f, long x);
GR_RUNTIME_API void feval_example(feval *f);
} /* namespace gr */
#endif /* INCLUDED_GR_FEVAL_H */

View File

@ -0,0 +1,194 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2007,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_FLOWGRAPH_H
#define INCLUDED_GR_RUNTIME_FLOWGRAPH_H
#include <gnuradio/api.h>
#include <gnuradio/basic_block.h>
#include <gnuradio/io_signature.h>
#include <iostream>
namespace gr {
/*!
* \brief Class representing a specific input or output graph endpoint
* \ingroup internal
*/
class GR_RUNTIME_API endpoint
{
private:
basic_block_sptr d_basic_block;
int d_port;
public:
endpoint() : d_basic_block(), d_port(0) { }
endpoint(basic_block_sptr block, int port) { d_basic_block = block; d_port = port; }
basic_block_sptr block() const { return d_basic_block; }
int port() const { return d_port; }
bool operator==(const endpoint &other) const;
};
inline bool endpoint::operator==(const endpoint &other) const
{
return (d_basic_block == other.d_basic_block &&
d_port == other.d_port);
}
// Hold vectors of gr::endpoint objects
typedef std::vector<endpoint> endpoint_vector_t;
typedef std::vector<endpoint>::iterator endpoint_viter_t;
/*!
*\brief Class representing a connection between to graph endpoints
*/
class GR_RUNTIME_API edge
{
public:
edge() : d_src(), d_dst() { };
edge(const endpoint &src, const endpoint &dst)
: d_src(src), d_dst(dst) { }
~edge();
const endpoint &src() const { return d_src; }
const endpoint &dst() const { return d_dst; }
private:
endpoint d_src;
endpoint d_dst;
};
// Hold vectors of gr::edge objects
typedef std::vector<edge> edge_vector_t;
typedef std::vector<edge>::iterator edge_viter_t;
// Create a shared pointer to a heap allocated flowgraph
// (types defined in runtime_types.h)
GR_RUNTIME_API flowgraph_sptr make_flowgraph();
/*!
* \brief Class representing a directed, acyclic graph of basic blocks
* \ingroup internal
*/
class GR_RUNTIME_API flowgraph
{
public:
friend GR_RUNTIME_API flowgraph_sptr make_flowgraph();
// Destruct an arbitrary flowgraph
~flowgraph();
// Connect two endpoints
void connect(const endpoint &src, const endpoint &dst);
// Disconnect two endpoints
void disconnect(const endpoint &src, const endpoint &dst);
// Connect an output port to an input port (convenience)
void connect(basic_block_sptr src_block, int src_port,
basic_block_sptr dst_block, int dst_port);
// Disconnect an input port from an output port (convenience)
void disconnect(basic_block_sptr src_block, int src_port,
basic_block_sptr dst_block, int dst_port);
// Validate connectivity, raise exception if invalid
void validate();
// Clear existing flowgraph
void clear();
// Return vector of edges
const edge_vector_t &edges() const { return d_edges; }
// Return vector of connected blocks
basic_block_vector_t calc_used_blocks();
// Return toplogically sorted vector of blocks. All the sources come first.
basic_block_vector_t topological_sort(basic_block_vector_t &blocks);
// Return vector of vectors of disjointly connected blocks,
// topologically sorted.
std::vector<basic_block_vector_t> partition();
protected:
basic_block_vector_t d_blocks;
edge_vector_t d_edges;
flowgraph();
std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs);
basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port);
edge_vector_t calc_upstream_edges(basic_block_sptr block);
bool has_block_p(basic_block_sptr block);
edge calc_upstream_edge(basic_block_sptr block, int port);
private:
void check_valid_port(gr::io_signature::sptr sig, int port);
void check_dst_not_used(const endpoint &dst);
void check_type_match(const endpoint &src, const endpoint &dst);
edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs
void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs);
basic_block_vector_t calc_downstream_blocks(basic_block_sptr block);
basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks);
basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks);
bool source_p(basic_block_sptr block);
void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output);
};
// Convenience functions
inline
void flowgraph::connect(basic_block_sptr src_block, int src_port,
basic_block_sptr dst_block, int dst_port)
{
connect(endpoint(src_block, src_port),
endpoint(dst_block, dst_port));
}
inline
void flowgraph::disconnect(basic_block_sptr src_block, int src_port,
basic_block_sptr dst_block, int dst_port)
{
disconnect(endpoint(src_block, src_port),
endpoint(dst_block, dst_port));
}
inline std::ostream&
operator <<(std::ostream &os, const endpoint endp)
{
os << endp.block()->alias() << ":" << endp.port();
return os;
}
inline std::ostream&
operator <<(std::ostream &os, const edge edge)
{
os << edge.src() << "->" << edge.dst();
return os;
}
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */

View File

@ -0,0 +1,108 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_FXPT_H
#define INCLUDED_GR_FXPT_H
#include <gnuradio/api.h>
#include <gnuradio/types.h>
namespace gr {
/*!
* \brief fixed point sine and cosine and friends.
* \ingroup misc
*
* fixed pt radians
* --------- --------
* -2**31 -pi
* 0 0
* 2**31-1 pi - epsilon
*/
class GR_RUNTIME_API fxpt
{
static const int WORDBITS = 32;
static const int NBITS = 10;
static const float s_sine_table[1 << NBITS][2];
static const float PI;
static const float TWO_TO_THE_31;
public:
static gr_int32
float_to_fixed(float x)
{
// Fold x into -PI to PI.
int d = (int)floor(x/2/PI+0.5);
x -= d*2*PI;
// And convert to an integer.
return (gr_int32) ((float) x * TWO_TO_THE_31 / PI);
}
static float
fixed_to_float (gr_int32 x)
{
return x * (PI / TWO_TO_THE_31);
}
/*!
* \brief Given a fixed point angle x, return float sine (x)
*/
static float
sin(gr_int32 x)
{
gr_uint32 ux = x;
int index = ux >> (WORDBITS - NBITS);
return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
}
/*
* \brief Given a fixed point angle x, return float cosine (x)
*/
static float
cos (gr_int32 x)
{
gr_uint32 ux = x + 0x40000000;
int index = ux >> (WORDBITS - NBITS);
return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
}
/*
* \brief Given a fixedpoint angle x, return float cos(x) and sin (x)
*/
static void sincos(gr_int32 x, float *s, float *c)
{
gr_uint32 ux = x;
int sin_index = ux >> (WORDBITS - NBITS);
*s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1];
ux = x + 0x40000000;
int cos_index = ux >> (WORDBITS - NBITS);
*c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1];
return;
}
};
} /* namespace gr */
#endif /* INCLUDED_GR_FXPT_H */

View File

@ -0,0 +1,160 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_FXPT_NCO_H
#define INCLUDED_GR_FXPT_NCO_H
#include <gnuradio/api.h>
#include <gnuradio/fxpt.h>
#include <gnuradio/gr_complex.h>
#include <stdint.h>
namespace gr {
/*!
* \brief Numerically Controlled Oscillator (NCO)
* \ingroup misc
*/
class /*GR_RUNTIME_API*/ fxpt_nco
{
uint32_t d_phase;
int32_t d_phase_inc;
public:
fxpt_nco() : d_phase(0), d_phase_inc(0) {}
~fxpt_nco() {}
// radians
void set_phase(float angle) {
d_phase = gr::fxpt::float_to_fixed(angle);
}
void adjust_phase(float delta_phase) {
d_phase += gr::fxpt::float_to_fixed(delta_phase);
}
// angle_rate is in radians / step
void set_freq(float angle_rate){
d_phase_inc = gr::fxpt::float_to_fixed(angle_rate);
}
// angle_rate is a delta in radians / step
void adjust_freq(float delta_angle_rate)
{
d_phase_inc += gr::fxpt::float_to_fixed(delta_angle_rate);
}
// increment current phase angle
void step()
{
d_phase += d_phase_inc;
}
void step(int n)
{
d_phase += d_phase_inc * n;
}
// units are radians / step
float get_phase() const { return gr::fxpt::fixed_to_float(d_phase); }
float get_freq() const { return gr::fxpt::fixed_to_float(d_phase_inc); }
// compute sin and cos for current phase angle
void sincos(float *sinx, float *cosx) const
{
*sinx = gr::fxpt::sin(d_phase);
*cosx = gr::fxpt::cos(d_phase);
}
// compute cos and sin for a block of phase angles
void sincos(gr_complex *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = gr_complex(gr::fxpt::cos(d_phase) * ampl, gr::fxpt::sin(d_phase) * ampl);
step();
}
}
// compute sin for a block of phase angles
void sin(float *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (float)(gr::fxpt::sin(d_phase) * ampl);
step();
}
}
// compute cos for a block of phase angles
void cos(float *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (float)(gr::fxpt::cos(d_phase) * ampl);
step ();
}
}
// compute sin for a block of phase angles
void sin(short *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (short)(gr::fxpt::sin(d_phase) * ampl);
step();
}
}
// compute cos for a block of phase angles
void cos(short *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (short)(gr::fxpt::cos(d_phase) * ampl);
step();
}
}
// compute sin for a block of phase angles
void sin(int *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (int)(gr::fxpt::sin(d_phase) * ampl);
step();
}
}
// compute cos for a block of phase angles
void cos(int *output, int noutput_items, double ampl=1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (int)(gr::fxpt::cos(d_phase) * ampl);
step();
}
}
// compute cos or sin for current phase angle
float cos() const { return gr::fxpt::cos(d_phase); }
float sin() const { return gr::fxpt::sin(d_phase); }
};
} /* namespace gr */
#endif /* INCLUDED_GR_FXPT_NCO_H */

View File

@ -0,0 +1,80 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2004,2005,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_FXPT_VCO_H
#define INCLUDED_GR_FXPT_VCO_H
#include <gnuradio/api.h>
#include <gnuradio/fxpt.h>
#include <gnuradio/gr_complex.h>
namespace gr {
/*!
* \brief Voltage Controlled Oscillator (VCO)
* \ingroup misc
*/
class /*GR_RUNTIME_API*/ fxpt_vco {
gr_int32 d_phase;
public:
fxpt_vco () : d_phase(0) {}
~fxpt_vco() {}
// radians
void set_phase(float angle) {
d_phase = fxpt::float_to_fixed(angle);
}
void adjust_phase(float delta_phase) {
d_phase += fxpt::float_to_fixed(delta_phase);
}
float get_phase() const {
return fxpt::fixed_to_float(d_phase);
}
// compute sin and cos for current phase angle
void sincos(float *sinx, float *cosx) const
{
*sinx = fxpt::sin(d_phase);
*cosx = fxpt::cos(d_phase);
}
// compute a block at a time
void cos(float *output, const float *input, int noutput_items, float k, float ampl = 1.0)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = (float)(fxpt::cos(d_phase) * ampl);
adjust_phase(input[i] * k);
}
}
// compute cos or sin for current phase angle
float cos() const { return fxpt::cos(d_phase); }
float sin() const { return fxpt::sin(d_phase); }
};
} /* namespace gr */
#endif /* INCLUDED_GR_FXPT_VCO_H */

View File

@ -0,0 +1,45 @@
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_COMPLEX_H
#define INCLUDED_GR_COMPLEX_H
#include <complex>
typedef std::complex<float> gr_complex;
typedef std::complex<double> gr_complexd;
inline bool is_complex (gr_complex x) { (void) x; return true;}
inline bool is_complex (gr_complexd x) { (void) x; return true;}
inline bool is_complex (float x) { (void) x; return false;}
inline bool is_complex (double x) { (void) x; return false;}
inline bool is_complex (int x) { (void) x; return false;}
inline bool is_complex (char x) { (void) x; return false;}
inline bool is_complex (short x) { (void) x; return false;}
// this doesn't really belong here, but there are worse places for it...
#define CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected,actual,delta) \
CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.real(), actual.real(), delta); \
CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.imag(), actual.imag(), delta);
#endif /* INCLUDED_GR_COMPLEX_H */

View File

@ -0,0 +1,192 @@
/* -*- c++ -*- */
/*
* Copyright 2006-2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_HIER_BLOCK2_H
#define INCLUDED_GR_RUNTIME_HIER_BLOCK2_H
#include <gnuradio/api.h>
#include <gnuradio/basic_block.h>
namespace gr {
/*!
* \brief public constructor for hier_block2
*/
GR_RUNTIME_API hier_block2_sptr
make_hier_block2(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
class hier_block2_detail;
/*!
* \brief Hierarchical container class for gr::block's and gr::hier_block2's
* \ingroup container_blk
* \ingroup base_blk
*/
class GR_RUNTIME_API hier_block2 : public basic_block
{
private:
friend class hier_block2_detail;
friend GR_RUNTIME_API hier_block2_sptr
make_hier_block2(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
/*!
* \brief Private implementation details of gr::hier_block2
*/
hier_block2_detail *d_detail;
protected:
hier_block2(void) {} // allows pure virtual interface sub-classes
hier_block2(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
public:
virtual ~hier_block2();
/*!
* \brief typedef for object returned from self().
*
* This type is only guaranteed to be passable to connect and
* disconnect. No other assumptions should be made about it.
*/
typedef basic_block_sptr opaque_self;
/*!
* \brief Return an object, representing the current block, which
* can be passed to connect.
*
* The returned object may only be used as an argument to connect
* or disconnect. Any other use of self() results in unspecified
* (erroneous) behavior.
*/
opaque_self self();
/*!
* \brief Add a stand-alone (possibly hierarchical) block to
* internal graph
*
* This adds a gr-block or hierarchical block to the internal
* graph without wiring it to anything else.
*/
void connect(basic_block_sptr block);
/*!
* \brief Add gr-blocks or hierarchical blocks to internal graph
* and wire together
*
* This adds (if not done earlier by another connect) a pair of
* gr-blocks or hierarchical blocks to the internal flowgraph, and
* wires the specified output port to the specified input port.
*/
void connect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port);
/*!
* \brief Remove a gr-block or hierarchical block from the
* internal flowgraph.
*
* This removes a gr-block or hierarchical block from the internal
* flowgraph, disconnecting it from other blocks as needed.
*/
void disconnect(basic_block_sptr block);
/*!
* \brief Disconnect a pair of gr-blocks or hierarchical blocks in
* internal flowgraph.
*
* This disconnects the specified input port from the specified
* output port of a pair of gr-blocks or hierarchical blocks.
*/
void disconnect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port);
/*!
* \brief Disconnect all connections in the internal flowgraph.
*
* This call removes all output port to input port connections in
* the internal flowgraph.
*/
void disconnect_all();
/*!
* Lock a flowgraph in preparation for reconfiguration. When an
* equal number of calls to lock() and unlock() have occurred, the
* flowgraph will be reconfigured.
*
* N.B. lock() and unlock() may not be called from a flowgraph
* thread (E.g., gr::block::work method) or deadlock will occur
* when reconfiguration happens.
*/
virtual void lock();
/*!
* Unlock a flowgraph in preparation for reconfiguration. When an
* equal number of calls to lock() and unlock() have occurred, the
* flowgraph will be reconfigured.
*
* N.B. lock() and unlock() may not be called from a flowgraph
* thread (E.g., gr::block::work method) or deadlock will occur
* when reconfiguration happens.
*/
virtual void unlock();
// This is a public method for ease of code organization, but should be
// ignored by the user.
flat_flowgraph_sptr flatten() const;
hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
/*!
* \brief Set the affinity of all blocks in hier_block2 to processor core \p n.
*
* \param mask a vector of ints of the core numbers available to this block.
*/
void set_processor_affinity(const std::vector<int> &mask);
/*!
* \brief Remove processor affinity for all blocks in hier_block2.
*/
void unset_processor_affinity();
/*!
* \brief Get the current processor affinity.
*
* \details This returns the processor affinity value for the first
* block in the hier_block2's list of blocks with the assumption
* that they have always only been set through the hier_block2's
* interface. If any block has been individually set, then this
* call could be misleading.
*/
std::vector<int> processor_affinity();
};
inline hier_block2_sptr cast_to_hier_block2_sptr(basic_block_sptr block) {
return boost::dynamic_pointer_cast<hier_block2, basic_block>(block);
}
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_HIER_BLOCK2_H */

View File

@ -0,0 +1,156 @@
/* -*- c++ -*- */
/*
* Copyright 2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_GNURADIO_HIGH_RES_TIMER_H
#define INCLUDED_GNURADIO_HIGH_RES_TIMER_H
#include <gnuradio/api.h>
////////////////////////////////////////////////////////////////////////
// Use architecture defines to determine the implementation
////////////////////////////////////////////////////////////////////////
#if defined(linux) || defined(__linux) || defined(__linux__)
#define GNURADIO_HRT_USE_CLOCK_GETTIME
#include <ctime>
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define GNURADIO_HRT_USE_QUERY_PERFORMANCE_COUNTER
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#define GNURADIO_HRT_USE_MACH_ABSOLUTE_TIME
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define GNURADIO_HRT_USE_CLOCK_GETTIME
#include <ctime>
#else
#define GNURADIO_HRT_USE_MICROSEC_CLOCK
#endif
////////////////////////////////////////////////////////////////////////
namespace gr {
//! Typedef for the timer tick count
typedef signed long long high_res_timer_type;
//! Get the current time in ticks
high_res_timer_type high_res_timer_now(void);
//! Get the current time in ticks - for performance monitoring
high_res_timer_type high_res_timer_now_perfmon(void);
//! Get the number of ticks per second
high_res_timer_type high_res_timer_tps(void);
//! Get the tick count at the epoch
high_res_timer_type high_res_timer_epoch(void);
#ifdef GNURADIO_HRT_USE_CLOCK_GETTIME
//! storage for high res timer type
GR_RUNTIME_API extern clockid_t high_res_timer_source;
#endif
} /* namespace gr */
////////////////////////////////////////////////////////////////////////
#ifdef GNURADIO_HRT_USE_CLOCK_GETTIME
inline gr::high_res_timer_type gr::high_res_timer_now(void){
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec;
}
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
timespec ts;
clock_gettime(high_res_timer_source, &ts);
return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec;
}
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
return 1000000000UL;
}
#endif /* GNURADIO_HRT_USE_CLOCK_GETTIME */
////////////////////////////////////////////////////////////////////////
#ifdef GNURADIO_HRT_USE_MACH_ABSOLUTE_TIME
#include <mach/mach_time.h>
inline gr::high_res_timer_type gr::high_res_timer_now(void){
return mach_absolute_time();
}
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
return gr::high_res_timer_now();
}
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
mach_timebase_info_data_t info;
mach_timebase_info(&info);
return gr::high_res_timer_type(info.numer*1000000000UL)/info.denom;
}
#endif
////////////////////////////////////////////////////////////////////////
#ifdef GNURADIO_HRT_USE_QUERY_PERFORMANCE_COUNTER
#include <Windows.h>
inline gr::high_res_timer_type gr::high_res_timer_now(void){
LARGE_INTEGER counts;
QueryPerformanceCounter(&counts);
return counts.QuadPart;
}
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
return gr::high_res_timer_now();
}
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return freq.QuadPart;
}
#endif
////////////////////////////////////////////////////////////////////////
#ifdef GNURADIO_HRT_USE_MICROSEC_CLOCK
#include <boost/date_time/posix_time/posix_time.hpp>
inline gr::high_res_timer_type gr::high_res_timer_now(void){
static const boost::posix_time::ptime epoch(boost::posix_time::from_time_t(0));
return (boost::posix_time::microsec_clock::universal_time() - epoch).ticks();
}
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
return gr::high_res_timer_now();
}
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
return boost::posix_time::time_duration::ticks_per_second();
}
#endif
////////////////////////////////////////////////////////////////////////
#include <boost/date_time/posix_time/posix_time.hpp>
inline gr::high_res_timer_type gr::high_res_timer_epoch(void){
static const double hrt_ticks_per_utc_ticks = gr::high_res_timer_tps()/double(boost::posix_time::time_duration::ticks_per_second());
boost::posix_time::time_duration utc = boost::posix_time::microsec_clock::universal_time() - boost::posix_time::from_time_t(0);
return gr::high_res_timer_now() - utc.ticks()*hrt_ticks_per_utc_ticks;
}
#endif /* INCLUDED_GNURADIO_HIGH_RES_TIMER_H */

View File

@ -0,0 +1,111 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_IO_SIGNATURE_H
#define INCLUDED_IO_SIGNATURE_H
#include <gnuradio/api.h>
#include <gnuradio/runtime_types.h>
namespace gr {
/*!
* \brief i/o signature for input and output ports.
* \brief misc
*/
class GR_RUNTIME_API io_signature
{
int d_min_streams;
int d_max_streams;
std::vector<int> d_sizeof_stream_item;
io_signature(int min_streams, int max_streams,
const std::vector<int> &sizeof_stream_items);
public:
typedef boost::shared_ptr<io_signature> sptr;
static const int IO_INFINITE = -1;
~io_signature();
/*!
* \brief Create an i/o signature
*
* \ingroup internal
* \param min_streams specify minimum number of streams (>= 0)
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
* \param sizeof_stream_item specify the size of the items in each stream
*/
static sptr make(int min_streams, int max_streams,
int sizeof_stream_item);
/*!
* \brief Create an i/o signature
*
* \param min_streams specify minimum number of streams (>= 0)
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
* \param sizeof_stream_item1 specify the size of the items in the first stream
* \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams
*/
static sptr make2(int min_streams, int max_streams,
int sizeof_stream_item1,
int sizeof_stream_item2);
/*!
* \brief Create an i/o signature
*
* \param min_streams specify minimum number of streams (>= 0)
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
* \param sizeof_stream_item1 specify the size of the items in the first stream
* \param sizeof_stream_item2 specify the size of the items in the second stream
* \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams
*/
static sptr make3(int min_streams, int max_streams,
int sizeof_stream_item1,
int sizeof_stream_item2,
int sizeof_stream_item3);
/*!
* \brief Create an i/o signature
*
* \param min_streams specify minimum number of streams (>= 0)
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
* \param sizeof_stream_items specify the size of the items in the streams
*
* If there are more streams than there are entries in
* sizeof_stream_items, the value of the last entry in
* sizeof_stream_items is used for the missing values.
* sizeof_stream_items must contain at least 1 entry.
*/
static sptr makev(int min_streams, int max_streams,
const std::vector<int> &sizeof_stream_items);
int min_streams() const { return d_min_streams; }
int max_streams() const { return d_max_streams; }
int sizeof_stream_item(int index) const;
std::vector<int> sizeof_stream_items() const;
};
} /* namespace gr */
#endif /* INCLUDED_IO_SIGNATURE_H */

View File

@ -0,0 +1,733 @@
/* -*- c++ -*- */
/*
* Copyright 2012-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*******************************************************************************
* Author: Mark Plett
* Description:
* The gr::logger module wraps the log4cpp library for logging in gnuradio
*******************************************************************************/
#ifndef INCLUDED_GR_LOGGER_H
#define INCLUDED_GR_LOGGER_H
/*!
* \ingroup logging
* \brief GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
*
*/
#ifndef ENABLE_GR_LOG
//#cmakedefine ENABLE_GR_LOG
#endif
#ifndef HAVE_LOG4CPP
//#cmakedefine HAVE_LOG4CPP
#endif
#ifdef _MSC_VER
typedef unsigned short mode_t;
#endif
#include <gnuradio/api.h>
#include <assert.h>
#include <iostream>
#include <time.h>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#ifdef ENABLE_GR_LOG
// We have three configurations... first logging to stdout/stderr
#ifndef HAVE_LOG4CPP
namespace gr {
//#warning GR logging Enabled and using std::cout
typedef std::string logger_ptr;
} /* namespace gr */
#define GR_LOG_DECLARE_LOGPTR(logger)
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
#define GR_LOG_ADD_APPENDER(logger,appender)
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
#define GR_GET_LOGGER_NAMES(names)
#define GR_RESET_CONFIGURATION()
#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl
#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl
#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl
#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl
#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl
#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl
#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);}
#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl
#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl
#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl
#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl
#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl
#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl
#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl
#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl
#define GR_LOG_ERRORIF(logger, cond, msg) { \
if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
#define GR_LOG_ASSERT(logger, cond, msg) { \
if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};}
#else /* HAVE_LOG4CPP */
// Second configuration...logging to log4cpp
#include <log4cpp/Category.hh>
#include <log4cpp/PropertyConfigurator.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
namespace gr {
/*!
* \brief GR_LOG macros
* \ingroup logging
*
* These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros
* are:
* LOG_DEBUG
* LOG_INFO
* LOG_WARN
* LOG_TRACE
* LOG_ERROR
* LOG_ALERT
* LOG_CRIT
* LOG_FATAL
* LOG_EMERG
*/
typedef log4cpp::Category* logger_ptr;
} /* namespace gr */
/* Macros for Programmatic Configuration */
#define GR_LOG_DECLARE_LOGPTR(logger) \
gr::logger_ptr logger;
#define GR_LOG_ASSIGN_LOGPTR(logger,name) \
logger = gr::logger_get_logger(name);
#define GR_CONFIG_LOGGER(config) \
gr::logger_config::load_config(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \
gr::logger_config::load_config(config,period)
#define GR_LOG_GETLOGGER(logger, name) \
gr::logger_ptr logger = gr::logger_get_logger(name);
#define GR_SET_LEVEL(name, level) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_set_level(logger,level);}
#define GR_LOG_SET_LEVEL(logger, level) \
gr::logger_set_level(logger, level);
#define GR_GET_LEVEL(name, level) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_get_level(logger,level);}
#define GR_LOG_GET_LEVEL(logger, level) \
gr::logger_get_level(logger,level);
#define GR_ADD_APPENDER(name, appender) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_appender(logger,appender);}
#define GR_LOG_ADD_APPENDER(logger, appender) { \
gr::logger_add_appender(logger, appender);}
#define GR_ADD_CONSOLE_APPENDER(name, target, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_console_appender(logger,target,pattern);}
#define GR_LOG_ADD_CONSOLE_APPENDER(logger, target, pattern) { \
gr::logger_add_console_appender(logger,target,pattern);}
#define GR_ADD_FILE_APPENDER(name, filename, append, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_file_appender(logger,filename,append,pattern);}
#define GR_LOG_ADD_FILE_APPENDER(logger, filename, append, pattern) { \
gr::logger_add_file_appender(logger,filename,append,pattern);}
#define GR_ADD_ROLLINGFILE_APPENDER(name, filename, filesize, bkup_index, append, mode, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger, filename, filesize, bkup_index, append, mode, pattern) { \
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
#define GR_GET_LOGGER_NAMES(names) { \
names = gr::logger_get_logger_names();}
#define GR_RESET_CONFIGURATION() \
gr::logger_config::reset_config();
/* Logger name referenced macros */
#define GR_DEBUG(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
#define GR_INFO(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;}
#define GR_NOTICE(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger << log4cpp::Priority::NOTICE << msg;}
#define GR_WARN(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;}
#define GR_ERROR(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;}
#define GR_CRIT(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;}
#define GR_ALERT(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;}
#define GR_FATAL(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;}
#define GR_EMERG(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;}
#define GR_ERRORIF(name, cond, msg) { \
if((cond)) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
}
#define GR_ASSERT(name, cond, msg) { \
if(!(cond)) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} \
assert(0); \
}
/* LoggerPtr Referenced Macros */
#define GR_LOG_DEBUG(logger, msg) { \
*logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
#define GR_LOG_INFO(logger, msg) { \
*logger << log4cpp::Priority::INFO << msg << log4cpp::eol;}
#define GR_LOG_NOTICE(logger, msg) { \
*logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;}
#define GR_LOG_WARN(logger, msg) { \
*logger << log4cpp::Priority::WARN << msg << log4cpp::eol;}
#define GR_LOG_ERROR(logger, msg) { \
*logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;}
#define GR_LOG_CRIT(logger, msg) { \
*logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;}
#define GR_LOG_ALERT(logger, msg) { \
*logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;}
#define GR_LOG_FATAL(logger, msg) { \
*logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;}
#define GR_LOG_EMERG(logger, msg) { \
*logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;}
#define GR_LOG_ERRORIF(logger,cond, msg) { \
if((cond)) { \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
}
#define GR_LOG_ASSERT(logger, cond, msg) { \
if(!(cond)) { \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol; \
assert(0);} \
}
namespace gr {
/*!
* \brief Class to control configuration of logger.
* This is a singleton that cna launch a thread to wathc a config file for changes
* \ingroup logging
*/
class logger_config
{
private:
/*! \brief filename of logger config file */
std::string filename;
/*! \brief Period (seconds) over which watcher thread checks config file for changes */
unsigned int watch_period;
/*! \brief Pointer to watch thread for config file changes */
boost::thread *watch_thread;
/*! \brief Watcher thread method
* /param filename Name of configuration file
* /param watch_period Seconds between checks for changes in config file
*/
static void watch_file(std::string filename,unsigned int watch_period);
static bool logger_configured;
logger_config()
{
} //!< Constructor
/*
rpcbasic_register_get<logger_config,std::string> rpc_get_filename;
rpcbasic_register_get<logger_config,int> rpc_get_watchperiod;
rpcbasic_register_get<logger_config,std::string> rpc_get_config;
rpcbasic_register_set<logger_config,std::string> rpc_set_config;
*/
logger_config(logger_config const&); //!<Copy constructor
void operator=(logger_config const&); //!<Assignment Operator
std::string get_filename4rpc() {
return filename;
}
int get_watchperiod4rpc(){return watch_period;};
std::string get_config4rpc() {
return filename;
}
void set_config4rpc(std::string set) {
printf("Set string was:%s\n", set.c_str());
}
/*! \brief destrcutor stops watch thread before exits */
~logger_config() {
stop_watch();
}
/*! \brief Instance getter for singleton. Only used by class. */
static logger_config& get_instance(void);
public:
/*! \brief Getter for config filename */
static std::string get_filename();
/*! \brief Getter for watch period */
static unsigned int get_watch_period();
/*! \brief Method to load configuration
* /param filename Name of configuration file
* /param watch_period Seconds between checks for changes in config file
*/
static void load_config(std::string filename,unsigned int watch_period=0);
/*! \brief Method to stop watcher thread */
static void stop_watch();
/*! \brief method to reset logger configuration */
static void reset_config(void);
};
/*!
* \brief Retrieve a pointer to a logger by name
*
* Retrives a logger pointer
* \p name.
*
* \param name Name of the logger for which a pointer is requested
*/
GR_RUNTIME_API logger_ptr logger_get_logger(std::string name);
/*!
* \brief Load logger's configuration file.
*
* Initialize the GNU Radio logger by loading the configuration file
* \p config_filename.
*
* \param config_filename The configuration file. Set to "" for the
* basic logger that outputs to the console.
*/
GR_RUNTIME_API bool logger_load_config(const std::string &config_filename="");
/*!
* \brief Reset logger's configuration file.
*
* Remove all appenders from loggers
*/
GR_RUNTIME_API void logger_reset_config(void);
/*!
* \brief Set the logger's output level.
*
* Sets the level of the logger. This takes a string that is
* translated to the standard levels and can be (case insensitive):
*
* \li off , notset
* \li debug
* \li info
* \li notice
* \li warn
* \li error
* \li crit
* \li alert
* \li fatal
* \li emerg
*
* \param logger the logger to set the level of.
* \param level string to set the level to.
*/
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
const std::string &level);
/*!
* \brief Set the logger's output level.
*
* Sets the level of the logger. This takes the actual Log4cpp::Priority
* data type, which can be:
*
* \li log4cpp::Priority::NOTSET
* \li log4cpp::Priority::DEBUG
* \li log4cpp::Priority::INFO
* \li log4cpp::Priority::NOTICE
* \li log4cpp::Priority::WARN
* \li log4cpp::Priority::ERROR
* \li log4cpp::Priority::CRIT
* \li log4cpp::Priority::ALERT
* \li log4cpp::Priority::FATAL
* \li log4cpp::Priority::EMERG
*
* \param logger the logger to set the level of.
* \param level new logger level of type Log4cpp::Priority
*/
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
log4cpp::Priority::Value level);
/*!
* \brief Get the logger's output level.
*
* Gets the level of the logger. This returns a string that
* corresponds to the standard levels and can be (case insensitive):
*
* \li notset
* \li debug
* \li info
* \li notice
* \li warn
* \li error
* \li crit
* \li alert
* \li fatal
* \li emerg
*
* \param logger the logger to get the level of.
* \param level string to get the level into.
*/
GR_RUNTIME_API void logger_get_level(logger_ptr logger, std::string &level);
/*!
* \brief Get the logger's output level.
*
* Gets the level of the logger. This returns the actual Log4cpp::Level
* data type, which can be:
*
* \li log4cpp::Priority::NOTSET
* \li log4cpp::Priority::DEBUG
* \li log4cpp::Priority::INFO
* \li log4cpp::Priority::NOTICE
* \li log4cpp::Priority::WARN
* \li log4cpp::Priority::ERROR
* \li log4cpp::Priority::CRIT
* \li log4cpp::Priority::ALERT
* \li log4cpp::Priority::FATAL
* \li log4cpp::Priority::EMERG
*
* \param logger the logger to get the level of.
* \param level of the logger.
*/
GR_RUNTIME_API void logger_get_level(logger_ptr logger,
log4cpp::Priority::Value &level);
/*!
* \brief Add console appender to a given logger
*
* Add console appender to a given logger
*
* \param logger Logger to which appender will be added
* \param appender Name of appender to add to logger
*/
GR_RUNTIME_API void logger_add_appender(logger_ptr logger,
std::string appender);
/*!
* \brief Add console appender to a given logger
*
* Add console appender to a given logger
*
* \param logger Logger to which appender will be added
* \param target Std target to write 'cout' or 'cerr' (default is cout)
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_console_appender(logger_ptr logger,
std::string target,
std::string pattern);
/*!
* \brief Add file appender to a given logger
*
* Add file appender to a given logger
*
* \param logger Logger to which appender will be added
* \param filename File to which log will be written
* \param append Overwrite or append to log file
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_file_appender(logger_ptr logger,
std::string filename,
bool append, std::string pattern);
/*!
* \brief Add rolling file appender to a given logger
*
* Add rolling file appender to a given logger
*
* \param logger Logger to which appender will be added
* \param filename File to which log will be written
* \param filesize Sizez of files to write
* \param bkup_index Number of files to write
* \param append Overwrite or append to log file
* \param mode Permissions to set on log file
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_rollingfile_appender(logger_ptr logger, std::string filename,
size_t filesize, int bkup_index, bool append,
mode_t mode,std::string pattern);
/*!
* \brief Add rolling file appender to a given logger
*
* Add rolling file appender to a given logger
*
* \return vector of string names of loggers
*/
GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
} /* namespace gr */
#endif /* HAVE_LOG4CPP */
// If Logger disable do nothing
#else /* ENABLE_GR_LOG */
namespace gr {
typedef void* logger_ptr;
} /* namespace gr */
#define GR_LOG_DECLARE_LOGPTR(logger)
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
#define GR_LOG_ADD_APPENDER(logger,appender)
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
#define GR_GET_LOGGER_NAMES(names)
#define GR_RESET_CONFIGURATION()
#define GR_DEBUG(name, msg)
#define GR_INFO(name, msg)
#define GR_NOTICE(name, msg)
#define GR_WARN(name, msg)
#define GR_ERROR(name, msg)
#define GR_ALERT(name, msg)
#define GR_CRIT(name, msg)
#define GR_FATAL(name, msg)
#define GR_EMERG(name, msg)
#define GR_ERRORIF(name, cond, msg)
#define GR_ASSERT(name, cond, msg)
#define GR_LOG_DEBUG(logger, msg)
#define GR_LOG_INFO(logger, msg)
#define GR_LOG_NOTICE(logger, msg)
#define GR_LOG_WARN(logger, msg)
#define GR_LOG_ERROR(logger, msg)
#define GR_LOG_ALERT(logger, msg)
#define GR_LOG_CRIT(logger, msg)
#define GR_LOG_FATAL(logger, msg)
#define GR_LOG_EMERG(logger, msg)
#define GR_LOG_ERRORIF(logger, cond, msg)
#define GR_LOG_ASSERT(logger, cond, msg)
#endif /* ENABLE_GR_LOG */
namespace gr {
// Even if logger is disabled we'll need for methods below to exist in python.
// The macros these call will be disabled if ENABLE_GR_LOG is undefined
/********************* Start Classes and Methods for Python ******************/
/*!
* \brief Logger class for referencing loggers in python. Not
* needed in C++ (use macros) Wraps and manipulates loggers for
* python as python has no macros
* \ingroup logging
*
*/
class logger
{
private:
/*! \brief logger pointer to logger associated wiith this wrapper class */
logger_ptr d_logger;
public:
/*!
* \brief contructor Provide name of logger to associate with this class
* \param logger_name Name of logger associated with class
*/
logger(std::string logger_name) {
GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name);
};
/*! \brief Destructor */
~logger(){;}
// Wrappers for logging macros
/*! \brief inline function, wrapper to set the logger level */
void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
/*! \brief inline function, wrapper to get the logger level */
void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
/*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */
void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
/*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */
void info(std::string msg){GR_LOG_INFO(d_logger,msg);}
/*! \brief inline function, wrapper for NOTICE message */
void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */
void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */
void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}
/*! \brief inline function, wrapper for NOTICE message */
void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}
/*! \brief inline function, wrapper for ALERT message */
void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}
/*! \brief inline function, wrapper for FATAL message */
void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}
/*! \brief inline function, wrapper for EMERG message */
void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}
/*! \brief inline function, Method to add appender to logger by
name (define appender in conf file) */
void add_appender(std::string appender) {
GR_LOG_ADD_APPENDER(d_logger, appender);
}
/*! \brief inline function, Method to add console appender to logger */
void add_console_appender(std::string target,std::string pattern) {
GR_LOG_ADD_CONSOLE_APPENDER(d_logger, target, pattern);
}
/*! \brief inline function, Method to add file appender to logger */
void add_file_appender(std::string filename, bool append, std::string pattern) {
GR_LOG_ADD_FILE_APPENDER(d_logger, filename, append, pattern);
}
/*! \brief inline function, Method to add rolling file appender to logger */
void add_rollingfile_appender(std::string filename, size_t filesize,
int bkup_index, bool append, mode_t mode,
std::string pattern) {
GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize,
bkup_index,append,mode,pattern);
}
};
} /* namespace gr */
/**************** Start Configuration Class and Methods for Python ************/
/*!
* \brief Function to call configuration macro from python.
* Note: Configuration is only updated if filename or watch_period has changed.
* \param config_filename Name of configuration file
* \param watch_period Seconds to wait between checking for changes in conf file.
* Watch_period defaults to 0 in which case the file is not watched for changes
*/
GR_RUNTIME_API void gr_logger_config(const std::string config_filename,
unsigned int watch_period = 0);
/*!
* \brief Function to return logger names to python
* \return Vector of name strings
*
*/
GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
/*!
* \brief Function to reset logger configuration from python
*
*/
GR_RUNTIME_API void gr_logger_reset_config(void);
#endif /* INCLUDED_GR_LOGGER_H */

View File

@ -0,0 +1,733 @@
/* -*- c++ -*- */
/*
* Copyright 2012-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*******************************************************************************
* Author: Mark Plett
* Description:
* The gr::logger module wraps the log4cpp library for logging in gnuradio
*******************************************************************************/
#ifndef INCLUDED_GR_LOGGER_H
#define INCLUDED_GR_LOGGER_H
/*!
* \ingroup logging
* \brief GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
*
*/
#ifndef ENABLE_GR_LOG
#cmakedefine ENABLE_GR_LOG
#endif
#ifndef HAVE_LOG4CPP
#cmakedefine HAVE_LOG4CPP
#endif
#ifdef _MSC_VER
typedef unsigned short mode_t;
#endif
#include <gnuradio/api.h>
#include <assert.h>
#include <iostream>
#include <time.h>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#ifdef ENABLE_GR_LOG
// We have three configurations... first logging to stdout/stderr
#ifndef HAVE_LOG4CPP
namespace gr {
//#warning GR logging Enabled and using std::cout
typedef std::string logger_ptr;
} /* namespace gr */
#define GR_LOG_DECLARE_LOGPTR(logger)
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
#define GR_LOG_ADD_APPENDER(logger,appender)
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
#define GR_GET_LOGGER_NAMES(names)
#define GR_RESET_CONFIGURATION()
#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl
#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl
#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl
#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl
#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl
#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl
#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);}
#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl
#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl
#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl
#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl
#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl
#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl
#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl
#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl
#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl
#define GR_LOG_ERRORIF(logger, cond, msg) { \
if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
#define GR_LOG_ASSERT(logger, cond, msg) { \
if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};}
#else /* HAVE_LOG4CPP */
// Second configuration...logging to log4cpp
#include <log4cpp/Category.hh>
#include <log4cpp/PropertyConfigurator.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
namespace gr {
/*!
* \brief GR_LOG macros
* \ingroup logging
*
* These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros
* are:
* LOG_DEBUG
* LOG_INFO
* LOG_WARN
* LOG_TRACE
* LOG_ERROR
* LOG_ALERT
* LOG_CRIT
* LOG_FATAL
* LOG_EMERG
*/
typedef log4cpp::Category* logger_ptr;
} /* namespace gr */
/* Macros for Programmatic Configuration */
#define GR_LOG_DECLARE_LOGPTR(logger) \
gr::logger_ptr logger;
#define GR_LOG_ASSIGN_LOGPTR(logger,name) \
logger = gr::logger_get_logger(name);
#define GR_CONFIG_LOGGER(config) \
gr::logger_config::load_config(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \
gr::logger_config::load_config(config,period)
#define GR_LOG_GETLOGGER(logger, name) \
gr::logger_ptr logger = gr::logger_get_logger(name);
#define GR_SET_LEVEL(name, level) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_set_level(logger,level);}
#define GR_LOG_SET_LEVEL(logger, level) \
gr::logger_set_level(logger, level);
#define GR_GET_LEVEL(name, level) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_get_level(logger,level);}
#define GR_LOG_GET_LEVEL(logger, level) \
gr::logger_get_level(logger,level);
#define GR_ADD_APPENDER(name, appender) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_appender(logger,appender);}
#define GR_LOG_ADD_APPENDER(logger, appender) { \
gr::logger_add_appender(logger, appender);}
#define GR_ADD_CONSOLE_APPENDER(name, target, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_console_appender(logger,target,pattern);}
#define GR_LOG_ADD_CONSOLE_APPENDER(logger, target, pattern) { \
gr::logger_add_console_appender(logger,target,pattern);}
#define GR_ADD_FILE_APPENDER(name, filename, append, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_file_appender(logger,filename,append,pattern);}
#define GR_LOG_ADD_FILE_APPENDER(logger, filename, append, pattern) { \
gr::logger_add_file_appender(logger,filename,append,pattern);}
#define GR_ADD_ROLLINGFILE_APPENDER(name, filename, filesize, bkup_index, append, mode, pattern) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger, filename, filesize, bkup_index, append, mode, pattern) { \
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
#define GR_GET_LOGGER_NAMES(names) { \
names = gr::logger_get_logger_names();}
#define GR_RESET_CONFIGURATION() \
gr::logger_config::reset_config();
/* Logger name referenced macros */
#define GR_DEBUG(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
#define GR_INFO(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;}
#define GR_NOTICE(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger << log4cpp::Priority::NOTICE << msg;}
#define GR_WARN(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;}
#define GR_ERROR(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;}
#define GR_CRIT(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;}
#define GR_ALERT(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;}
#define GR_FATAL(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;}
#define GR_EMERG(name, msg) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;}
#define GR_ERRORIF(name, cond, msg) { \
if((cond)) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
}
#define GR_ASSERT(name, cond, msg) { \
if(!(cond)) { \
gr::logger_ptr logger = gr::logger_get_logger(name); \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} \
assert(0); \
}
/* LoggerPtr Referenced Macros */
#define GR_LOG_DEBUG(logger, msg) { \
*logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
#define GR_LOG_INFO(logger, msg) { \
*logger << log4cpp::Priority::INFO << msg << log4cpp::eol;}
#define GR_LOG_NOTICE(logger, msg) { \
*logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;}
#define GR_LOG_WARN(logger, msg) { \
*logger << log4cpp::Priority::WARN << msg << log4cpp::eol;}
#define GR_LOG_ERROR(logger, msg) { \
*logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;}
#define GR_LOG_CRIT(logger, msg) { \
*logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;}
#define GR_LOG_ALERT(logger, msg) { \
*logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;}
#define GR_LOG_FATAL(logger, msg) { \
*logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;}
#define GR_LOG_EMERG(logger, msg) { \
*logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;}
#define GR_LOG_ERRORIF(logger,cond, msg) { \
if((cond)) { \
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
}
#define GR_LOG_ASSERT(logger, cond, msg) { \
if(!(cond)) { \
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol; \
assert(0);} \
}
namespace gr {
/*!
* \brief Class to control configuration of logger.
* This is a singleton that cna launch a thread to wathc a config file for changes
* \ingroup logging
*/
class logger_config
{
private:
/*! \brief filename of logger config file */
std::string filename;
/*! \brief Period (seconds) over which watcher thread checks config file for changes */
unsigned int watch_period;
/*! \brief Pointer to watch thread for config file changes */
boost::thread *watch_thread;
/*! \brief Watcher thread method
* /param filename Name of configuration file
* /param watch_period Seconds between checks for changes in config file
*/
static void watch_file(std::string filename,unsigned int watch_period);
static bool logger_configured;
logger_config()
{
} //!< Constructor
/*
rpcbasic_register_get<logger_config,std::string> rpc_get_filename;
rpcbasic_register_get<logger_config,int> rpc_get_watchperiod;
rpcbasic_register_get<logger_config,std::string> rpc_get_config;
rpcbasic_register_set<logger_config,std::string> rpc_set_config;
*/
logger_config(logger_config const&); //!<Copy constructor
void operator=(logger_config const&); //!<Assignment Operator
std::string get_filename4rpc() {
return filename;
}
int get_watchperiod4rpc(){return watch_period;};
std::string get_config4rpc() {
return filename;
}
void set_config4rpc(std::string set) {
printf("Set string was:%s\n", set.c_str());
}
/*! \brief destrcutor stops watch thread before exits */
~logger_config() {
stop_watch();
}
/*! \brief Instance getter for singleton. Only used by class. */
static logger_config& get_instance(void);
public:
/*! \brief Getter for config filename */
static std::string get_filename();
/*! \brief Getter for watch period */
static unsigned int get_watch_period();
/*! \brief Method to load configuration
* /param filename Name of configuration file
* /param watch_period Seconds between checks for changes in config file
*/
static void load_config(std::string filename,unsigned int watch_period=0);
/*! \brief Method to stop watcher thread */
static void stop_watch();
/*! \brief method to reset logger configuration */
static void reset_config(void);
};
/*!
* \brief Retrieve a pointer to a logger by name
*
* Retrives a logger pointer
* \p name.
*
* \param name Name of the logger for which a pointer is requested
*/
GR_RUNTIME_API logger_ptr logger_get_logger(std::string name);
/*!
* \brief Load logger's configuration file.
*
* Initialize the GNU Radio logger by loading the configuration file
* \p config_filename.
*
* \param config_filename The configuration file. Set to "" for the
* basic logger that outputs to the console.
*/
GR_RUNTIME_API bool logger_load_config(const std::string &config_filename="");
/*!
* \brief Reset logger's configuration file.
*
* Remove all appenders from loggers
*/
GR_RUNTIME_API void logger_reset_config(void);
/*!
* \brief Set the logger's output level.
*
* Sets the level of the logger. This takes a string that is
* translated to the standard levels and can be (case insensitive):
*
* \li off , notset
* \li debug
* \li info
* \li notice
* \li warn
* \li error
* \li crit
* \li alert
* \li fatal
* \li emerg
*
* \param logger the logger to set the level of.
* \param level string to set the level to.
*/
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
const std::string &level);
/*!
* \brief Set the logger's output level.
*
* Sets the level of the logger. This takes the actual Log4cpp::Priority
* data type, which can be:
*
* \li log4cpp::Priority::NOTSET
* \li log4cpp::Priority::DEBUG
* \li log4cpp::Priority::INFO
* \li log4cpp::Priority::NOTICE
* \li log4cpp::Priority::WARN
* \li log4cpp::Priority::ERROR
* \li log4cpp::Priority::CRIT
* \li log4cpp::Priority::ALERT
* \li log4cpp::Priority::FATAL
* \li log4cpp::Priority::EMERG
*
* \param logger the logger to set the level of.
* \param level new logger level of type Log4cpp::Priority
*/
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
log4cpp::Priority::Value level);
/*!
* \brief Get the logger's output level.
*
* Gets the level of the logger. This returns a string that
* corresponds to the standard levels and can be (case insensitive):
*
* \li notset
* \li debug
* \li info
* \li notice
* \li warn
* \li error
* \li crit
* \li alert
* \li fatal
* \li emerg
*
* \param logger the logger to get the level of.
* \param level string to get the level into.
*/
GR_RUNTIME_API void logger_get_level(logger_ptr logger, std::string &level);
/*!
* \brief Get the logger's output level.
*
* Gets the level of the logger. This returns the actual Log4cpp::Level
* data type, which can be:
*
* \li log4cpp::Priority::NOTSET
* \li log4cpp::Priority::DEBUG
* \li log4cpp::Priority::INFO
* \li log4cpp::Priority::NOTICE
* \li log4cpp::Priority::WARN
* \li log4cpp::Priority::ERROR
* \li log4cpp::Priority::CRIT
* \li log4cpp::Priority::ALERT
* \li log4cpp::Priority::FATAL
* \li log4cpp::Priority::EMERG
*
* \param logger the logger to get the level of.
* \param level of the logger.
*/
GR_RUNTIME_API void logger_get_level(logger_ptr logger,
log4cpp::Priority::Value &level);
/*!
* \brief Add console appender to a given logger
*
* Add console appender to a given logger
*
* \param logger Logger to which appender will be added
* \param appender Name of appender to add to logger
*/
GR_RUNTIME_API void logger_add_appender(logger_ptr logger,
std::string appender);
/*!
* \brief Add console appender to a given logger
*
* Add console appender to a given logger
*
* \param logger Logger to which appender will be added
* \param target Std target to write 'cout' or 'cerr' (default is cout)
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_console_appender(logger_ptr logger,
std::string target,
std::string pattern);
/*!
* \brief Add file appender to a given logger
*
* Add file appender to a given logger
*
* \param logger Logger to which appender will be added
* \param filename File to which log will be written
* \param append Overwrite or append to log file
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_file_appender(logger_ptr logger,
std::string filename,
bool append, std::string pattern);
/*!
* \brief Add rolling file appender to a given logger
*
* Add rolling file appender to a given logger
*
* \param logger Logger to which appender will be added
* \param filename File to which log will be written
* \param filesize Sizez of files to write
* \param bkup_index Number of files to write
* \param append Overwrite or append to log file
* \param mode Permissions to set on log file
* \param pattern Formating pattern for log messages
*/
GR_RUNTIME_API void logger_add_rollingfile_appender(logger_ptr logger, std::string filename,
size_t filesize, int bkup_index, bool append,
mode_t mode,std::string pattern);
/*!
* \brief Add rolling file appender to a given logger
*
* Add rolling file appender to a given logger
*
* \return vector of string names of loggers
*/
GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
} /* namespace gr */
#endif /* HAVE_LOG4CPP */
// If Logger disable do nothing
#else /* ENABLE_GR_LOG */
namespace gr {
typedef void* logger_ptr;
} /* namespace gr */
#define GR_LOG_DECLARE_LOGPTR(logger)
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
#define GR_LOG_ADD_APPENDER(logger,appender)
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
#define GR_GET_LOGGER_NAMES(names)
#define GR_RESET_CONFIGURATION()
#define GR_DEBUG(name, msg)
#define GR_INFO(name, msg)
#define GR_NOTICE(name, msg)
#define GR_WARN(name, msg)
#define GR_ERROR(name, msg)
#define GR_ALERT(name, msg)
#define GR_CRIT(name, msg)
#define GR_FATAL(name, msg)
#define GR_EMERG(name, msg)
#define GR_ERRORIF(name, cond, msg)
#define GR_ASSERT(name, cond, msg)
#define GR_LOG_DEBUG(logger, msg)
#define GR_LOG_INFO(logger, msg)
#define GR_LOG_NOTICE(logger, msg)
#define GR_LOG_WARN(logger, msg)
#define GR_LOG_ERROR(logger, msg)
#define GR_LOG_ALERT(logger, msg)
#define GR_LOG_CRIT(logger, msg)
#define GR_LOG_FATAL(logger, msg)
#define GR_LOG_EMERG(logger, msg)
#define GR_LOG_ERRORIF(logger, cond, msg)
#define GR_LOG_ASSERT(logger, cond, msg)
#endif /* ENABLE_GR_LOG */
namespace gr {
// Even if logger is disabled we'll need for methods below to exist in python.
// The macros these call will be disabled if ENABLE_GR_LOG is undefined
/********************* Start Classes and Methods for Python ******************/
/*!
* \brief Logger class for referencing loggers in python. Not
* needed in C++ (use macros) Wraps and manipulates loggers for
* python as python has no macros
* \ingroup logging
*
*/
class logger
{
private:
/*! \brief logger pointer to logger associated wiith this wrapper class */
logger_ptr d_logger;
public:
/*!
* \brief contructor Provide name of logger to associate with this class
* \param logger_name Name of logger associated with class
*/
logger(std::string logger_name) {
GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name);
};
/*! \brief Destructor */
~logger(){;}
// Wrappers for logging macros
/*! \brief inline function, wrapper to set the logger level */
void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
/*! \brief inline function, wrapper to get the logger level */
void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
/*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */
void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
/*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */
void info(std::string msg){GR_LOG_INFO(d_logger,msg);}
/*! \brief inline function, wrapper for NOTICE message */
void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */
void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */
void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}
/*! \brief inline function, wrapper for NOTICE message */
void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}
/*! \brief inline function, wrapper for ALERT message */
void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}
/*! \brief inline function, wrapper for FATAL message */
void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}
/*! \brief inline function, wrapper for EMERG message */
void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}
/*! \brief inline function, Method to add appender to logger by
name (define appender in conf file) */
void add_appender(std::string appender) {
GR_LOG_ADD_APPENDER(d_logger, appender);
}
/*! \brief inline function, Method to add console appender to logger */
void add_console_appender(std::string target,std::string pattern) {
GR_LOG_ADD_CONSOLE_APPENDER(d_logger, target, pattern);
}
/*! \brief inline function, Method to add file appender to logger */
void add_file_appender(std::string filename, bool append, std::string pattern) {
GR_LOG_ADD_FILE_APPENDER(d_logger, filename, append, pattern);
}
/*! \brief inline function, Method to add rolling file appender to logger */
void add_rollingfile_appender(std::string filename, size_t filesize,
int bkup_index, bool append, mode_t mode,
std::string pattern) {
GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize,
bkup_index,append,mode,pattern);
}
};
} /* namespace gr */
/**************** Start Configuration Class and Methods for Python ************/
/*!
* \brief Function to call configuration macro from python.
* Note: Configuration is only updated if filename or watch_period has changed.
* \param config_filename Name of configuration file
* \param watch_period Seconds to wait between checking for changes in conf file.
* Watch_period defaults to 0 in which case the file is not watched for changes
*/
GR_RUNTIME_API void gr_logger_config(const std::string config_filename,
unsigned int watch_period = 0);
/*!
* \brief Function to return logger names to python
* \return Vector of name strings
*
*/
GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
/*!
* \brief Function to reset logger configuration from python
*
*/
GR_RUNTIME_API void gr_logger_reset_config(void);
#endif /* INCLUDED_GR_LOGGER_H */

View File

@ -0,0 +1,227 @@
/* -*- c++ -*- */
/*
* Copyright 2003,2005,2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*
* mathematical odds and ends.
*/
#ifndef _GR_MATH_H_
#define _GR_MATH_H_
#include <cmath>
#include <gnuradio/api.h>
#include <gnuradio/gr_complex.h>
namespace gr {
static inline bool
is_power_of_2(long x)
{
return x != 0 && (x & (x-1)) == 0;
}
/*!
* \brief Fast arc tangent using table lookup and linear interpolation
* \ingroup misc
*
* \param y component of input vector
* \param x component of input vector
* \returns float angle angle of vector (x, y) in radians
*
* This function calculates the angle of the vector (x,y) based on a
* table lookup and linear interpolation. The table uses a 256 point
* table covering -45 to +45 degrees and uses symetry to determine
* the final angle value in the range of -180 to 180 degrees. Note
* that this function uses the small angle approximation for values
* close to zero. This routine calculates the arc tangent with an
* average error of +/- 0.045 degrees.
*/
GR_RUNTIME_API float fast_atan2f(float y, float x);
static inline float
fast_atan2f(gr_complex z)
{
return fast_atan2f(z.imag(), z.real());
}
/* This bounds x by +/- clip without a branch */
static inline float
branchless_clip(float x, float clip)
{
float x1 = fabsf(x+clip);
float x2 = fabsf(x-clip);
x1 -= x2;
return 0.5*x1;
}
static inline float
clip(float x, float clip)
{
float y = x;
if(x > clip)
y = clip;
else if(x < -clip)
y = -clip;
return y;
}
// Slicer Functions
static inline unsigned int
binary_slicer(float x)
{
if(x >= 0)
return 1;
else
return 0;
}
static inline unsigned int
quad_45deg_slicer(float r, float i)
{
unsigned int ret = 0;
if((r >= 0) && (i >= 0))
ret = 0;
else if((r < 0) && (i >= 0))
ret = 1;
else if((r < 0) && (i < 0))
ret = 2;
else
ret = 3;
return ret;
}
static inline unsigned int
quad_0deg_slicer(float r, float i)
{
unsigned int ret = 0;
if(fabsf(r) > fabsf(i)) {
if(r > 0)
ret = 0;
else
ret = 2;
}
else {
if(i > 0)
ret = 1;
else
ret = 3;
}
return ret;
}
static inline unsigned int
quad_45deg_slicer(gr_complex x)
{
return quad_45deg_slicer(x.real(), x.imag());
}
static inline unsigned int
quad_0deg_slicer(gr_complex x)
{
return quad_0deg_slicer(x.real(), x.imag());
}
// Branchless Slicer Functions
static inline unsigned int
branchless_binary_slicer(float x)
{
return (x >= 0);
}
static inline unsigned int
branchless_quad_0deg_slicer(float r, float i)
{
unsigned int ret = 0;
ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10)
ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
return ret;
}
static inline unsigned int
branchless_quad_0deg_slicer(gr_complex x)
{
return branchless_quad_0deg_slicer(x.real(), x.imag());
}
static inline unsigned int
branchless_quad_45deg_slicer(float r, float i)
{
char ret = (r <= 0);
ret |= ((i <= 0) << 1);
return (ret ^ ((ret & 0x2) >> 0x1));
}
static inline unsigned int
branchless_quad_45deg_slicer(gr_complex x)
{
return branchless_quad_45deg_slicer(x.real(), x.imag());
}
/*!
* \param x any value
* \param pow2 must be a power of 2
* \returns \p x rounded down to a multiple of \p pow2.
*/
static inline size_t
p2_round_down(size_t x, size_t pow2)
{
return x & -pow2;
}
/*!
* \param x any value
* \param pow2 must be a power of 2
* \returns \p x rounded up to a multiple of \p pow2.
*/
static inline size_t
p2_round_up(size_t x, size_t pow2)
{
return p2_round_down(x + pow2 - 1, pow2);
}
/*!
* \param x any value
* \param pow2 must be a power of 2
* \returns \p x modulo \p pow2.
*/
static inline size_t
p2_modulo(size_t x, size_t pow2)
{
return x & (pow2 - 1);
}
/*!
* \param x any value
* \param pow2 must be a power of 2
* \returns \p pow2 - (\p x modulo \p pow2).
*/
static inline size_t
p2_modulo_neg(size_t x, size_t pow2)
{
return pow2 - p2_modulo(x, pow2);
}
} /* namespace gr */
#endif /* _GR_MATH_H_ */

View File

@ -0,0 +1,39 @@
/* -*- c++ -*- */
/*
* Copyright 2005 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_MISC_H
#define INCLUDED_GR_MISC_H
#include <gnuradio/api.h>
#include <gnuradio/types.h>
GR_RUNTIME_API unsigned int
gr_rounduppow2(unsigned int n);
// FIXME should be template
GR_RUNTIME_API void gr_zero_vector(std::vector<float> &v);
GR_RUNTIME_API void gr_zero_vector(std::vector<double> &v);
GR_RUNTIME_API void gr_zero_vector(std::vector<int> &v);
GR_RUNTIME_API void gr_zero_vector(std::vector<gr_complex> &v);
#endif /* INCLUDED_GR_MISC_H */

View File

@ -0,0 +1,152 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_PREFS_H
#define INCLUDED_GR_PREFS_H
#include <gnuradio/api.h>
#include <string>
#include <map>
#include <gnuradio/thread/thread.h>
namespace gr {
typedef std::map< std::string, std::map<std::string, std::string> > config_map_t;
typedef std::map< std::string, std::map<std::string, std::string> >::iterator config_map_itr;
typedef std::map<std::string, std::string> config_map_elem_t;
typedef std::map<std::string, std::string>::iterator config_map_elem_itr;
/*!
* \brief Base class for representing user preferences a la windows INI files.
* \ingroup misc
*
* The real implementation is in Python, and is accessable from C++
* via the magic of SWIG directors.
*/
class GR_RUNTIME_API prefs
{
public:
static prefs *singleton();
static void set_singleton(prefs *p);
prefs();
virtual ~prefs();
/*!
* \brief Returns the configuration options as a string.
*/
std::string to_string();
/*!
* \brief Saves the configuration settings to
* ${HOME}/.gnuradio/config.conf.
*
* WARNING: this will overwrite your current config.conf file.
*/
void save();
/*!
* \brief Does \p section exist?
*/
virtual bool has_section(const std::string &section);
/*!
* \brief Does \p option exist?
*/
virtual bool has_option(const std::string &section,
const std::string &option);
/*!
* \brief If option exists return associated value; else
* default_val.
*/
virtual const std::string get_string(const std::string &section,
const std::string &option,
const std::string &default_val);
/*!
* \brief Set or add a string \p option to \p section with value
* \p val.
*/
virtual void set_string(const std::string &section,
const std::string &option,
const std::string &val);
/*!
* \brief If option exists and value can be converted to bool,
* return it; else default_val.
*/
virtual bool get_bool(const std::string &section,
const std::string &option,
bool default_val);
/*!
* \brief Set or add a bool \p option to \p section with value \p val.
*/
virtual void set_bool(const std::string &section,
const std::string &option,
bool val);
/*!
* \brief If option exists and value can be converted to long,
* return it; else default_val.
*/
virtual long get_long(const std::string &section,
const std::string &option,
long default_val);
/*!
* \brief Set or add a long \p option to \p section with value \p val.
*/
virtual void set_long(const std::string &section,
const std::string &option,
long val);
/*!
* \brief If option exists and value can be converted to double,
* return it; else default_val.
*/
virtual double get_double(const std::string &section,
const std::string &option,
double default_val);
/*!
* \brief Set or add a double \p option to \p section with value \p val.
*/
virtual void set_double(const std::string &section,
const std::string &option,
double val);
protected:
virtual std::vector<std::string> _sys_prefs_filenames();
virtual void _read_files();
virtual void _convert_to_map(const std::string &conf);
virtual char * option_to_env(std::string section, std::string option);
private:
gr::thread::mutex d_mutex;
config_map_t d_config_map;
};
} /* namespace gr */
#endif /* INCLUDED_GR_PREFS_H */

View File

@ -0,0 +1,81 @@
/* -*- c++ -*- */
/*
* Copyright 2002 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RANDOM_H
#define INCLUDED_GR_RANDOM_H
#include <gnuradio/api.h>
#include <gnuradio/gr_complex.h>
// While rand(3) specifies RAND_MAX, random(3) says that the output
// ranges from 0 to 2^31-1 but does not specify a macro to denote
// this. We define RANDOM_MAX for cleanliness. We must omit the
// definition for systems that have made the same choice. (Note that
// random(3) is from 4.2BSD, and not specified by POSIX.)
#ifndef RANDOM_MAX
static const int RANDOM_MAX = 2147483647; // 2^31-1
#endif /* RANDOM_MAX */
#include <stdlib.h>
namespace gr {
/*!
* \brief pseudo random number generator
* \ingroup math_blk
*/
class GR_RUNTIME_API random
{
protected:
static const int NTAB = 32;
long d_seed;
long d_iy;
long d_iv[NTAB];
int d_iset;
float d_gset;
public:
random(long seed=3021);
void reseed(long seed);
/*!
* \brief uniform random deviate in the range [0.0, 1.0)
*/
float ran1();
/*!
* \brief normally distributed deviate with zero mean and variance 1
*/
float gasdev();
float laplacian();
float impulse(float factor);
float rayleigh();
gr_complex rayleigh_complex();
};
} /* namespace gr */
#endif /* INCLUDED_GR_RANDOM_H */

View File

@ -0,0 +1,39 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_REALTIME_H
#define INCLUDED_GR_REALTIME_H
#include <gnuradio/api.h>
#include <gnuradio/realtime_impl.h>
namespace gr {
/*!
* \brief If possible, enable high-priority "real time" scheduling.
* \ingroup misc
*/
GR_RUNTIME_API rt_status_t enable_realtime_scheduling();
} /* namespace gr */
#endif /* INCLUDED_GR_REALTIME_H */

View File

@ -0,0 +1,96 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GNURADIO_REALTIME_H
#define INCLUDED_GNURADIO_REALTIME_H
#include <gnuradio/api.h>
#include <stdexcept>
/*!
* \brief System independent way to ask for realtime scheduling
*
* \sa sys_pri.h
*/
namespace gr {
typedef enum {
RT_OK = 0,
RT_NOT_IMPLEMENTED,
RT_NO_PRIVS,
RT_OTHER_ERROR
} rt_status_t;
enum rt_sched_policy {
RT_SCHED_RR = 0, // round robin
RT_SCHED_FIFO = 1, // first in first out
};
namespace impl {
/*
* Define the range for our virtual priorities (don't change
* these)
*
* Processes (or threads) with numerically higher priority values
* are scheduled before processes with numerically lower priority
* values. Thus, the value returned by rt_priority_max() will be
* greater than the value returned by rt_priority_min().
*/
static inline int rt_priority_min() { return 0; }
static inline int rt_priority_max() { return 15; }
static inline int rt_priority_default() { return 1; }
struct GR_RUNTIME_API rt_sched_param {
int priority;
rt_sched_policy policy;
rt_sched_param()
: priority(rt_priority_default()), policy(RT_SCHED_RR){}
rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR)
{
if(priority_ < rt_priority_min() || priority_ > rt_priority_max())
throw std::invalid_argument("rt_sched_param: priority out of range");
priority = priority_;
policy = policy_;
}
};
/*!
* \brief If possible, enable "realtime" scheduling.
* \ingroup misc
*
* In general, this means that the code will be scheduled before
* any non-realtime (normal) processes. Note that if your code
* contains an non-blocking infinite loop and you enable realtime
* scheduling, it's possible to hang the system.
*/
// NOTE: If you change this, you need to change the code in
// gnuradio-runtime/swig/realtime.i, see note there.
GR_RUNTIME_API rt_status_t enable_realtime_scheduling(rt_sched_param = rt_sched_param());
} /* namespace impl */
} /* namespace gr */
#endif /* INCLUDED_GNURADIO_REALTIME_H */

View File

@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_TYPES_H
#define INCLUDED_GR_RUNTIME_TYPES_H
#include <gnuradio/api.h>
#include <gnuradio/types.h>
namespace gr {
/*
* typedefs for smart pointers we use throughout the runtime system
*/
class basic_block;
class block;
class block_detail;
class buffer;
class buffer_reader;
class hier_block2;
class flat_flowgraph;
class flowgraph;
class top_block;
typedef boost::shared_ptr<basic_block> basic_block_sptr;
typedef boost::shared_ptr<block> block_sptr;
typedef boost::shared_ptr<block_detail> block_detail_sptr;
typedef boost::shared_ptr<buffer> buffer_sptr;
typedef boost::shared_ptr<buffer_reader> buffer_reader_sptr;
typedef boost::shared_ptr<hier_block2> hier_block2_sptr;
typedef boost::shared_ptr<flat_flowgraph> flat_flowgraph_sptr;
typedef boost::shared_ptr<flowgraph> flowgraph_sptr;
typedef boost::shared_ptr<top_block> top_block_sptr;
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_TYPES_H */

View File

@ -0,0 +1,35 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_SINCOS_H
#define INCLUDED_GR_SINCOS_H
#include <gnuradio/api.h>
namespace gr {
// compute sine and cosine at the same time
GR_RUNTIME_API void sincos (double x, double *sin, double *cos);
GR_RUNTIME_API void sincosf (float x, float *sin, float *cos);
}
#endif /* INCLUDED_GR_SINCOS_H */

View File

@ -0,0 +1,57 @@
/* -*- c++ -*- */
/*
* Copyright 2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_GR_RUNTIME_SPTR_MAGIC_H
#define INCLUDED_GR_RUNTIME_SPTR_MAGIC_H
#include <gnuradio/api.h>
#include <boost/shared_ptr.hpp>
namespace gr {
class basic_block;
class hier_block2;
}
namespace gnuradio {
namespace detail {
class GR_RUNTIME_API sptr_magic
{
public:
static boost::shared_ptr<gr::basic_block> fetch_initial_sptr(gr::basic_block *p);
static void create_and_stash_initial_sptr(gr::hier_block2 *p);
};
};
/*
* \brief New! Improved! Standard method to get/create the
* boost::shared_ptr for a block.
*/
template<class T>
boost::shared_ptr<T>
get_initial_sptr(T *p)
{
return boost::dynamic_pointer_cast<T, gr::basic_block>
(detail::sptr_magic::fetch_initial_sptr(p));
}
}
#endif /* INCLUDED_GR_RUNTIME_SPTR_MAGIC_H */

View File

@ -0,0 +1,69 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_SYNC_BLOCK_H
#define INCLUDED_GR_RUNTIME_SYNC_BLOCK_H
#include <gnuradio/api.h>
#include <gnuradio/block.h>
namespace gr {
/*!
* \brief synchronous 1:1 input to output with history
* \ingroup base_blk
*
* Override work to provide the signal processing implementation.
*/
class GR_RUNTIME_API sync_block : public block
{
protected:
sync_block(void) {} // allows pure virtual interface sub-classes
sync_block(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature);
public:
/*!
* \brief just like gr::block::general_work, only this arranges to
* call consume_each for you
*
* The user must override work to define the signal processing code
*/
virtual int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) = 0;
// gr::sync_block overrides these to assist work
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
int fixed_rate_ninput_to_noutput(int ninput);
int fixed_rate_noutput_to_ninput(int noutput);
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_SYNC_BLOCK_H */

View File

@ -0,0 +1,72 @@
/* -*- c++ -*- */
/*
* Copyright 2004, 2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H
#define INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H
#include <gnuradio/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
/*!
* \brief synchronous N:1 input to output with history
* \ingroup base_blk
*
* Override work to provide the signal processing implementation.
*/
class GR_RUNTIME_API sync_decimator : public sync_block
{
private:
unsigned d_decimation;
protected:
sync_decimator(void) {} // allows pure virtual interface sub-classes
sync_decimator(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature,
unsigned decimation);
public:
unsigned decimation() const { return d_decimation; }
void set_decimation(unsigned decimation)
{
d_decimation = decimation;
set_relative_rate(1.0 / decimation);
}
// gr::sync_decimator overrides these to assist work
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
// derived classes should override work
int fixed_rate_ninput_to_noutput(int ninput);
int fixed_rate_noutput_to_ninput(int noutput);
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H */

View File

@ -0,0 +1,74 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H
#define INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H
#include <gnuradio/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
/*!
* \brief synchronous 1:N input to output with history
* \ingroup base_blk
*
* Override work to provide the signal processing implementation.
*/
class GR_RUNTIME_API sync_interpolator : public sync_block
{
private:
unsigned d_interpolation;
protected:
sync_interpolator(void) {} // allows pure virtual interface sub-classes
sync_interpolator(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature,
unsigned interpolation);
public:
unsigned interpolation() const { return d_interpolation; }
void set_interpolation(unsigned interpolation)
{
d_interpolation = interpolation;
set_relative_rate(1.0 * interpolation);
set_output_multiple(interpolation);
}
// gr::sync_interpolator overrides these to assist work
void forecast(int noutput_items,
gr_vector_int &ninput_items_required);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
// derived classes should override work
int fixed_rate_ninput_to_noutput(int ninput);
int fixed_rate_noutput_to_ninput(int noutput);
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H */

View File

@ -0,0 +1,37 @@
/*
* Copyright 2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef GR_SYS_PATHS_H
#define GR_SYS_PATHS_H
#include <gnuradio/api.h>
namespace gr {
//! directory to create temporary files
GR_RUNTIME_API const char *tmp_path();
//! directory to store application data
GR_RUNTIME_API const char *appdata_path();
} /* namespace gr */
#endif /* GR_SYS_PATHS_H */

View File

@ -0,0 +1,156 @@
/* -*- c++ -*- */
/*
* Copyright 2009-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_THREAD_H
#define INCLUDED_THREAD_H
#include <gnuradio/api.h>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
#include <vector>
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
namespace gr {
namespace thread {
typedef boost::thread thread;
typedef boost::mutex mutex;
typedef boost::unique_lock<boost::mutex> scoped_lock;
typedef boost::condition_variable condition_variable;
/*! \brief a system-dependent typedef for the underlying thread type.
*/
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
typedef HANDLE gr_thread_t;
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
typedef pthread_t gr_thread_t;
#else
typedef pthread_t gr_thread_t;
#endif
/*! \brief Get the current thread's ID as a gr_thread_t
*
* We use this when setting the thread affinity or any other
* low-level thread settings. Can be called withing a GNU Radio
* block to get a reference to its current thread ID.
*/
GR_RUNTIME_API gr_thread_t get_current_thread_id();
/*! \brief Bind the current thread to a set of cores.
*
* Wrapper for system-dependent calls to set the affinity of the
* current thread to the processor mask. The mask is simply a
* 1-demensional vector containing the processor or core number
* from 0 to N-1 for N cores.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_bind_to_processor(const std::vector<int> &mask);
/*! \brief Convineince function to bind the current thread to a single core.
*
* Wrapper for system-dependent calls to set the affinity of the
* current thread to a given core from 0 to N-1 for N cores.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_bind_to_processor(int n);
/*! \brief Bind a thread to a set of cores.
*
* Wrapper for system-dependent calls to set the affinity of the
* given thread ID to the processor mask. The mask is simply a
* 1-demensional vector containing the processor or core number
* from 0 to N-1 for N cores.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_bind_to_processor(gr_thread_t thread,
const std::vector<int> &mask);
/*! \brief Convineince function to bind the a thread to a single core.
*
* Wrapper for system-dependent calls to set the affinity of the
* given thread ID to a given core from 0 to N-1 for N cores.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_bind_to_processor(gr_thread_t thread,
unsigned int n);
/*! \brief Remove any thread-processor affinity for the current thread.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_unbind();
/*! \brief Remove any thread-processor affinity for a given thread ID.
*
* Note: this does not work on OSX; it is a nop call since OSX
* does not support the concept of thread affinity (and what they
* do support in this way since 10.5 is not what we want or can
* use in this fashion).
*/
GR_RUNTIME_API void thread_unbind(gr_thread_t thread);
/*! \brief get current thread priority for a given thread ID
*
* Note: this does not work on OSX
*/
GR_RUNTIME_API int thread_priority(gr_thread_t thread);
/*! \brief get current thread priority for a given thread ID
*
* Note: this does not work on OSX
*/
GR_RUNTIME_API int set_thread_priority(gr_thread_t thread, int priority);
} /* namespace thread */
} /* namespace gr */
#endif /* INCLUDED_THREAD_H */

View File

@ -0,0 +1,72 @@
/* -*- c++ -*- */
/*
* Copyright 2008,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_THREAD_BODY_WRAPPER_H
#define INCLUDED_THREAD_BODY_WRAPPER_H
#include <gnuradio/api.h>
#include <gnuradio/thread/thread.h>
#include <exception>
#include <iostream>
namespace gr {
namespace thread {
GR_RUNTIME_API void mask_signals();
template <class F>
class thread_body_wrapper
{
private:
F d_f;
std::string d_name;
public:
explicit thread_body_wrapper(F f, const std::string &name="")
: d_f(f), d_name(name) {}
void operator()()
{
mask_signals();
try {
d_f();
}
catch(boost::thread_interrupted const &)
{
}
catch(std::exception const &e)
{
std::cerr << "thread[" << d_name << "]: "
<< e.what() << std::endl;
}
catch(...)
{
std::cerr << "thread[" << d_name << "]: "
<< "caught unrecognized exception\n";
}
}
};
} /* namespace thread */
} /* namespace gr */
#endif /* INCLUDED_THREAD_BODY_WRAPPER_H */

View File

@ -0,0 +1,48 @@
/* -*- c++ -*- */
/*
* Copyright (C) 2001-2003 William E. Kempf
* Copyright (C) 2007 Anthony Williams
* Copyright 2008,2009 Free Software Foundation, Inc.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* This was extracted from Boost 1.35.0 and fixed.
*/
#ifndef INCLUDED_THREAD_GROUP_H
#define INCLUDED_THREAD_GROUP_H
#include <gnuradio/api.h>
#include <gnuradio/thread/thread.h>
#include <boost/utility.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/function.hpp>
namespace gr {
namespace thread {
class GR_RUNTIME_API thread_group : public boost::noncopyable
{
public:
thread_group();
~thread_group();
boost::thread* create_thread(const boost::function0<void>& threadfunc);
void add_thread(boost::thread* thrd);
void remove_thread(boost::thread* thrd);
void join_all();
void interrupt_all();
size_t size() const;
private:
std::list<boost::thread*> m_threads;
mutable boost::shared_mutex m_mutex;
};
} /* namespace thread */
} /* namespace gr */
#endif /* INCLUDED_THREAD_GROUP_H */

View File

@ -0,0 +1,146 @@
/* -*- c++ -*- */
/*
* Copyright 2007-2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_TOP_BLOCK_H
#define INCLUDED_GR_TOP_BLOCK_H
#include <gnuradio/api.h>
#include <gnuradio/hier_block2.h>
namespace gr {
class top_block_impl;
GR_RUNTIME_API top_block_sptr make_top_block(const std::string &name);
/*!
*\brief Top-level hierarchical block representing a flowgraph
* \ingroup container_blk
*/
class GR_RUNTIME_API top_block : public hier_block2
{
private:
friend GR_RUNTIME_API top_block_sptr
make_top_block(const std::string &name);
top_block_impl *d_impl;
protected:
top_block(const std::string &name);
public:
~top_block();
/*!
* \brief The simple interface to running a flowgraph.
*
* Calls start() then wait(). Used to run a flowgraph that will
* stop on its own, or when another thread will call stop().
*
* \param max_noutput_items the maximum number of output items
* allowed for any block in the flowgraph. This passes through to
* the start function; see that function for more details.
*/
void run(int max_noutput_items=100000000);
/*!
* Start the contained flowgraph. Creates one or more threads to
* execute the flow graph. Returns to the caller once the threads
* are created. Calling start() on a top_block that is already
* started IS an error.
*
* \param max_noutput_items the maximum number of output items
* allowed for any block in the flowgraph; the noutput_items can
* always be less than this, but this will cap it as a
* maximum. Use this to adjust the maximum latency a flowgraph can
* exhibit.
*/
void start(int max_noutput_items=100000000);
/*!
* Stop the running flowgraph. Notifies each thread created by the
* scheduler to shutdown, then returns to caller. Calling stop()
* on a top_block that is already stopped IS NOT an error.
*/
void stop();
/*!
* Wait for a flowgraph to complete. Flowgraphs complete when
* either (1) all blocks indicate that they are done (typically
* only when using blocks.file_source, or blocks.head, or (2)
* after stop() has been called to request shutdown. Calling wait
* on a top_block that is not running IS NOT an error (wait
* returns w/o blocking).
*/
void wait();
/*!
* Lock a flowgraph in preparation for reconfiguration. When an
* equal number of calls to lock() and unlock() have occurred, the
* flowgraph will be reconfigured.
*
* N.B. lock() and unlock() may not be called from a flowgraph
* thread (E.g., block::work method) or deadlock will occur
* when reconfiguration happens.
*/
virtual void lock();
/*!
* Unlock a flowgraph in preparation for reconfiguration. When an
* equal number of calls to lock() and unlock() have occurred, the
* flowgraph will be reconfigured.
*
* N.B. lock() and unlock() may not be called from a flowgraph thread
* (E.g., block::work method) or deadlock will occur when
* reconfiguration happens.
*/
virtual void unlock();
/*!
* Returns a string that lists the edge connections in the
* flattened flowgraph.
*/
std::string edge_list();
/*!
* Displays flattened flowgraph edges and block connectivity
*/
void dump();
//! Get the number of max noutput_items in the flowgraph
int max_noutput_items();
//! Set the maximum number of noutput_items in the flowgraph
void set_max_noutput_items(int nmax);
top_block_sptr to_top_block(); // Needed for Python type coercion
void setup_rpc();
};
inline top_block_sptr cast_to_top_block_sptr(basic_block_sptr block) {
return boost::dynamic_pointer_cast<top_block, basic_block>(block);
}
} /* namespce gr */
#endif /* INCLUDED_GR_TOP_BLOCK_H */

View File

@ -0,0 +1,92 @@
/* -*- c++ -*- */
/*
* Copyright 2008,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_GR_TPB_DETAIL_H
#define INCLUDED_GR_TPB_DETAIL_H
#include <gnuradio/api.h>
#include <gnuradio/thread/thread.h>
#include <deque>
namespace gr {
class block_detail;
/*!
* \brief used by thread-per-block scheduler
*/
struct GR_RUNTIME_API tpb_detail {
gr::thread::mutex mutex; //< protects all vars
bool input_changed;
gr::thread::condition_variable input_cond;
bool output_changed;
gr::thread::condition_variable output_cond;
public:
tpb_detail()
: input_changed(false), output_changed(false) { }
//! Called by us to tell all our upstream blocks that their output
//! may have changed.
void notify_upstream(block_detail *d);
//! Called by us to tell all our downstream blocks that their
//! input may have changed.
void notify_downstream(block_detail *d);
//! Called by us to notify both upstream and downstream
void notify_neighbors(block_detail *d);
//! Called by pmt msg posters
void notify_msg() {
input_cond.notify_one();
output_cond.notify_one();
}
//! Called by us
void clear_changed()
{
gr::thread::scoped_lock guard(mutex);
input_changed = false;
output_changed = false;
}
private:
//! Used by notify_downstream
void set_input_changed()
{
gr::thread::scoped_lock guard(mutex);
input_changed = true;
input_cond.notify_one();
}
//! Used by notify_upstream
void set_output_changed()
{
gr::thread::scoped_lock guard(mutex);
output_changed = true;
output_cond.notify_one();
}
};
} /* namespace gr */
#endif /* INCLUDED_GR_TPB_DETAIL_H */

View File

@ -0,0 +1,65 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_TYPES_H
#define INCLUDED_GR_TYPES_H
#include <gnuradio/api.h>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <stddef.h> // size_t
#include <gnuradio/gr_complex.h>
typedef std::vector<int> gr_vector_int;
typedef std::vector<unsigned int> gr_vector_uint;
typedef std::vector<float> gr_vector_float;
typedef std::vector<double> gr_vector_double;
typedef std::vector<void *> gr_vector_void_star;
typedef std::vector<const void *> gr_vector_const_void_star;
/*
* #include <config.h> must be placed beforehand
* in the source file including gnuradio/types.h for
* the following to work correctly
*/
#ifdef HAVE_STDINT_H
#include <stdint.h>
typedef int16_t gr_int16;
typedef int32_t gr_int32;
typedef int64_t gr_int64;
typedef uint16_t gr_uint16;
typedef uint32_t gr_uint32;
typedef uint64_t gr_uint64;
#else
/*
* Note: these defaults may be wrong on 64-bit systems
*/
typedef short gr_int16;
typedef int gr_int32;
typedef long long gr_int64;
typedef unsigned short gr_uint16;
typedef unsigned int gr_uint32;
typedef unsigned long long gr_uint64;
#endif /* HAVE_STDINT_H */
#endif /* INCLUDED_GR_TYPES_H */

View File

@ -49,6 +49,144 @@ GR_OSMOSDR_APPEND_LIBS(
${GNURADIO_BLOCKS_LIBRARIES}
)
########################################################################
# Set up built-in GNU Radio runtime component
########################################################################
GR_REGISTER_COMPONENT("Built-in GNU Radio runtime" ENABLE_RUNTIME RUNTIME_MODE)
if(ENABLE_RUNTIME)
message(STATUS "")
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/ConfigChecks.cmake)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/runtime)
GR_OSMOSDR_APPEND_SRCS(
runtime/blocks/throttle_impl.cc
runtime/blocks/null_sink_impl.cc
runtime/blocks/null_source_impl.cc
runtime/math/fast_atan2f.cc
runtime/math//fxpt.cc
runtime/math/random.cc
runtime/math/sincos.cc
runtime/thread/thread.cc
runtime/thread/thread_body_wrapper.cc
runtime/thread/thread_group.cc
runtime/basic_block.cc
runtime/block.cc
runtime/block_detail.cc
runtime/block_executor.cc
runtime/block_gateway_impl.cc
runtime/block_registry.cc
runtime/buffer.cc
runtime/circular_file.cc
runtime/feval.cc
runtime/flat_flowgraph.cc
runtime/flowgraph.cc
runtime/hier_block2.cc
runtime/hier_block2_detail.cc
runtime/high_res_timer.cc
runtime/io_signature.cc
runtime/local_sighandler.cc
runtime/logger.cc
runtime/misc.cc
runtime/pagesize.cc
runtime/prefs.cc
runtime/realtime.cc
runtime/realtime_impl.cc
runtime/scheduler.cc
runtime/scheduler_sts.cc
runtime/scheduler_tpb.cc
runtime/single_threaded_scheduler.cc
runtime/sptr_magic.cc
runtime/sync_block.cc
runtime/sys_paths.cc
runtime/top_block.cc
runtime/top_block_impl.cc
runtime/tpb_detail.cc
runtime/tpb_thread_body.cc
runtime/vmcircbuf.cc
runtime/vmcircbuf_createfilemapping.cc
runtime/vmcircbuf_mmap_shm_open.cc
runtime/vmcircbuf_mmap_tmpfile.cc
runtime/vmcircbuf_prefs.cc
runtime/vmcircbuf_sysv_shm.cc
)
########################################################################
# Handle the generated constants
########################################################################
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
"import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())"
OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(GR_VERSION "built-in")
message(STATUS "Loading prefix ${prefix} into constants...")
message(STATUS "Loading SYSCONFDIR ${SYSCONFDIR} into constants...")
message(STATUS "Loading GR_PREFSDIR ${GR_PREFSDIR} into constants...")
message(STATUS "Loading build date ${BUILD_DATE} into constants...")
message(STATUS "Loading version ${GR_VERSION} into constants...")
#double escape for windows backslash path separators
string(REPLACE "\\" "\\\\" prefix ${prefix})
string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR})
string(REPLACE "\\" "\\\\" GR_PREFSDIR ${GR_PREFSDIR})
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/runtime/constants.cc.in
${CMAKE_CURRENT_BINARY_DIR}/constants.cc
@ONLY)
GR_OSMOSDR_APPEND_SRCS(${CMAKE_CURRENT_BINARY_DIR}/constants.cc)
# PowerPC workaround for posix_memalign
# Might not be needed, but we'll keep it for now.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
GR_OSMOSDR_APPEND_SRCS(runtime/posix_memalign.cc)
endif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
########################################################################
# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines.
# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1
########################################################################
if(WIN32)
OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF)
else(WIN32)
OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON)
endif(WIN32)
message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.")
if(TRY_SHM_VMCIRCBUF)
ADD_DEFINITIONS( -DTRY_SHM_VMCIRCBUF )
endif(TRY_SHM_VMCIRCBUF)
########################################################################
# Add libraries for winsock2.h on Windows
########################################################################
CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
if(HAVE_WINDOWS_H)
include_directories(${CMAKE_SOURCE_DIR}/cmake/msvc)
ADD_DEFINITIONS(-DHAVE_WINDOWS_H -DUSING_WINSOCK -DWIN32_LEAN_AND_MEAN)
ADD_DEFINITIONS(-DNOMINMAX -D_USE_MATH_DEFINES)
ADD_DEFINITIONS(/MP -D_CRT_SECURE_NO_WARNINGS -DD_CRT_SECURE_NO_DEPRECATE)
MESSAGE(STATUS "Adding windows libs to gnuradio osmosdr lib...")
GR_OSMOSDR_APPEND_LIBS(WS2_32.lib WSock32.lib)
endif(HAVE_WINDOWS_H)
########################################################################
# Need to link with librt for shm_*
########################################################################
if(LINUX)
GR_OSMOSDR_APPEND_LIBS(rt)
endif()
endif(ENABLE_RUNTIME)
########################################################################
# Setup IQBalance component
########################################################################
@ -169,3 +307,8 @@ ADD_LIBRARY(gnuradio-osmosdr SHARED ${gr_osmosdr_srcs})
TARGET_LINK_LIBRARIES(gnuradio-osmosdr ${gr_osmosdr_libs})
SET_TARGET_PROPERTIES(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_osmosdr_EXPORTS")
GR_LIBRARY_FOO(gnuradio-osmosdr)
if(ENABLE_RUNTIME)
SET_TARGET_PROPERTIES(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
SET_TARGET_PROPERTIES(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_blocks_EXPORTS")
endif(ENABLE_RUNTIME)

204
lib/ConfigChecks.cmake Normal file
View File

@ -0,0 +1,204 @@
# Copyright 2010-2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
INCLUDE(GrMiscUtils)
INCLUDE(CheckCXXSourceCompiles)
IF(MSVC) #add this directory for our provided headers
LIST(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/msvc)
ENDIF(MSVC)
#GR_CHECK_HDR_N_DEF(netdb.h HAVE_NETDB_H)
#GR_CHECK_HDR_N_DEF(sys/time.h HAVE_SYS_TIME_H)
GR_CHECK_HDR_N_DEF(sys/types.h HAVE_SYS_TYPES_H)
#GR_CHECK_HDR_N_DEF(sys/select.h HAVE_SYS_SELECT_H)
#GR_CHECK_HDR_N_DEF(sys/socket.h HAVE_SYS_SOCKET_H)
#GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H)
GR_CHECK_HDR_N_DEF(io.h HAVE_IO_H)
GR_CHECK_HDR_N_DEF(sys/mman.h HAVE_SYS_MMAN_H)
GR_CHECK_HDR_N_DEF(sys/ipc.h HAVE_SYS_IPC_H)
GR_CHECK_HDR_N_DEF(sys/shm.h HAVE_SYS_SHM_H)
GR_CHECK_HDR_N_DEF(signal.h HAVE_SIGNAL_H)
#GR_CHECK_HDR_N_DEF(netinet/in.h HAVE_NETINET_IN_H)
#GR_CHECK_HDR_N_DEF(arpa/inet.h HAVE_ARPA_INET_H)
#GR_CHECK_HDR_N_DEF(byteswap.h HAVE_BYTESWAP_H)
#GR_CHECK_HDR_N_DEF(linux/ppdev.h HAVE_LINUX_PPDEV_H)
#GR_CHECK_HDR_N_DEF(dev/ppbus/ppi.h HAVE_DEV_PPBUS_PPI_H)
GR_CHECK_HDR_N_DEF(unistd.h HAVE_UNISTD_H)
#GR_CHECK_HDR_N_DEF(malloc.h HAVE_MALLOC_H)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <stdio.h>
int main(){snprintf(0, 0, 0); return 0;}
" HAVE_SNPRINTF
)
GR_ADD_COND_DEF(HAVE_SNPRINTF)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <signal.h>
int main(){sigaction(0, 0, 0); return 0;}
" HAVE_SIGACTION
)
GR_ADD_COND_DEF(HAVE_SIGACTION)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <sys/select.h>
int main(){select(0, 0, 0, 0, 0); return 0;}
" HAVE_SELECT
)
GR_ADD_COND_DEF(HAVE_SELECT)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <unistd.h>
int main(){sysconf(0); return 0;}
" HAVE_SYSCONF
)
GR_ADD_COND_DEF(HAVE_SYSCONF)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <unistd.h>
int main(){getpagesize(); return 0;}
" HAVE_GETPAGESIZE
)
GR_ADD_COND_DEF(HAVE_GETPAGESIZE)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <Winbase.h>
int main(){Sleep(0); return 0;}
" HAVE_SSLEEP
)
GR_ADD_COND_DEF(HAVE_SSLEEP)
CHECK_CXX_SOURCE_COMPILES("
#include <time.h>
int main(){nanosleep(0, 0); return 0;}
" HAVE_NANOSLEEP
)
GR_ADD_COND_DEF(HAVE_NANOSLEEP)
CHECK_CXX_SOURCE_COMPILES("
#include <sys/time.h>
int main(){gettimeofday(0, 0); return 0;}
" HAVE_GETTIMEOFDAY
)
GR_ADD_COND_DEF(HAVE_GETTIMEOFDAY)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <stdlib.h>
int main(){posix_memalign(0, 0, 0); return 0;}
" HAVE_POSIX_MEMALIGN
)
GR_ADD_COND_DEF(HAVE_POSIX_MEMALIGN)
CHECK_CXX_SOURCE_COMPILES("
#include <malloc.h>
int main(){valloc(0); return 0;}
" HAVE_VALLOC
)
GR_ADD_COND_DEF(HAVE_VALLOC)
ADD_DEFINITIONS(-DALIGNED_MALLOC=0)
########################################################################
SET(CMAKE_REQUIRED_LIBRARIES -lpthread)
CHECK_CXX_SOURCE_COMPILES("
#include <signal.h>
int main(){pthread_sigmask(0, 0, 0); return 0;}
" HAVE_PTHREAD_SIGMASK
)
GR_ADD_COND_DEF(HAVE_PTHREAD_SIGMASK)
SET(CMAKE_REQUIRED_LIBRARIES)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <windows.h>
int main(){
HANDLE handle;
int size;
LPCTSTR lpName;
handle = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // max. object size
size, // buffer size
lpName); // name of mapping object
return 0;
} " HAVE_CREATEFILEMAPPING
)
GR_ADD_COND_DEF(HAVE_CREATEFILEMAPPING)
########################################################################
SET(CMAKE_REQUIRED_LIBRARIES -lrt)
CHECK_CXX_SOURCE_COMPILES("
#include <sys/types.h>
#include <sys/mman.h>
int main(){shm_open(0, 0, 0); return 0;}
" HAVE_SHM_OPEN
)
GR_ADD_COND_DEF(HAVE_SHM_OPEN)
SET(CMAKE_REQUIRED_LIBRARIES)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#define _GNU_SOURCE
#include <math.h>
int main(){double x, sin, cos; sincos(x, &sin, &cos); return 0;}
" HAVE_SINCOS
)
GR_ADD_COND_DEF(HAVE_SINCOS)
CHECK_CXX_SOURCE_COMPILES("
#define _GNU_SOURCE
#include <math.h>
int main(){float x, sin, cos; sincosf(x, &sin, &cos); return 0;}
" HAVE_SINCOSF
)
GR_ADD_COND_DEF(HAVE_SINCOSF)
CHECK_CXX_SOURCE_COMPILES("
#include <math.h>
int main(){sinf(0); return 0;}
" HAVE_SINF
)
GR_ADD_COND_DEF(HAVE_SINF)
CHECK_CXX_SOURCE_COMPILES("
#include <math.h>
int main(){cosf(0); return 0;}
" HAVE_COSF
)
GR_ADD_COND_DEF(HAVE_COSF)
########################################################################
CHECK_CXX_SOURCE_COMPILES("
#include <sys/mman.h>
int main(){mmap(0, 0, 0, 0, 0, 0); return 0;}
" HAVE_MMAP
)
GR_ADD_COND_DEF(HAVE_MMAP)

View File

@ -0,0 +1,77 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2012-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/basic_block.h>
#include <gnuradio/block_registry.h>
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace gr {
static long s_next_id = 0;
static long s_ncurrently_allocated = 0;
long
basic_block_ncurrently_allocated()
{
return s_ncurrently_allocated;
}
basic_block::basic_block(const std::string &name,
io_signature::sptr input_signature,
io_signature::sptr output_signature)
: d_name(name),
d_input_signature(input_signature),
d_output_signature(output_signature),
d_unique_id(s_next_id++),
d_symbolic_id(global_block_registry.block_register(this)),
d_symbol_name(global_block_registry.register_symbolic_name(this)),
d_color(WHITE),
d_rpc_set(false)
{
s_ncurrently_allocated++;
}
basic_block::~basic_block()
{
s_ncurrently_allocated--;
global_block_registry.block_unregister(this);
}
basic_block_sptr
basic_block::to_basic_block()
{
return shared_from_this();
}
void
basic_block::set_block_alias(std::string name)
{
global_block_registry.register_symbolic_name(this, name);
}
} /* namespace gr */

626
lib/runtime/block.cc Normal file
View File

@ -0,0 +1,626 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/block.h>
#include <gnuradio/block_registry.h>
#include <gnuradio/block_detail.h>
#include <gnuradio/prefs.h>
#include <stdexcept>
#include <iostream>
namespace gr {
block::block(const std::string &name,
io_signature::sptr input_signature,
io_signature::sptr output_signature)
: basic_block(name, input_signature, output_signature),
d_output_multiple (1),
d_output_multiple_set(false),
d_unaligned(0),
d_is_unaligned(false),
d_relative_rate (1.0),
d_history(1),
d_fixed_rate(false),
d_max_noutput_items_set(false),
d_max_noutput_items(0),
d_min_noutput_items(0),
d_priority(-1),
d_pc_rpc_set(false),
d_max_output_buffer(std::max(output_signature->max_streams(),1), -1),
d_min_output_buffer(std::max(output_signature->max_streams(),1), -1)
{
global_block_registry.register_primitive(alias(), this);
#ifdef ENABLE_GR_LOG
#ifdef HAVE_LOG4CPP
prefs *p = prefs::singleton();
std::string config_file = p->get_string("LOG", "log_config", "");
std::string log_level = p->get_string("LOG", "log_level", "off");
std::string log_file = p->get_string("LOG", "log_file", "");
std::string debug_level = p->get_string("LOG", "debug_level", "off");
std::string debug_file = p->get_string("LOG", "debug_file", "");
GR_CONFIG_LOGGER(config_file);
GR_LOG_GETLOGGER(LOG, "gr_log." + alias());
GR_LOG_SET_LEVEL(LOG, log_level);
if(log_file.size() > 0) {
if(log_file == "stdout") {
GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cout","gr::log :%p: %c{1} - %m%n");
}
else if(log_file == "stderr") {
GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cerr","gr::log :%p: %c{1} - %m%n");
}
else {
GR_LOG_ADD_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n");
}
}
d_logger = LOG;
GR_LOG_GETLOGGER(DLOG, "gr_log_debug." + alias());
GR_LOG_SET_LEVEL(DLOG, debug_level);
if(debug_file.size() > 0) {
if(debug_file == "stdout") {
GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cout","gr::debug :%p: %c{1} - %m%n");
}
else if(debug_file == "stderr") {
GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cerr", "gr::debug :%p: %c{1} - %m%n");
}
else {
GR_LOG_ADD_FILE_APPENDER(DLOG, debug_file, true, "%r :%p: %c{1} - %m%n");
}
}
d_debug_logger = DLOG;
#endif /* HAVE_LOG4CPP */
#else /* ENABLE_GR_LOG */
d_logger = NULL;
d_debug_logger = NULL;
#endif /* ENABLE_GR_LOG */
}
block::~block()
{
global_block_registry.unregister_primitive(alias());
}
// stub implementation: 1:1
void
block::forecast(int noutput_items, gr_vector_int &ninput_items_required)
{
unsigned ninputs = ninput_items_required.size ();
for(unsigned i = 0; i < ninputs; i++)
ninput_items_required[i] = noutput_items + history() - 1;
}
// default implementation
bool
block::start()
{
return true;
}
bool
block::stop()
{
return true;
}
void
block::set_output_multiple(int multiple)
{
if(multiple < 1)
throw std::invalid_argument("block::set_output_multiple");
d_output_multiple_set = true;
d_output_multiple = multiple;
}
void
block::set_alignment(int multiple)
{
if(multiple < 1)
throw std::invalid_argument("block::set_alignment_multiple");
d_output_multiple = multiple;
}
void
block::set_unaligned(int na)
{
// unaligned value must be less than 0 and it doesn't make sense
// that it's larger than the alignment value.
if((na < 0) || (na > d_output_multiple))
throw std::invalid_argument("block::set_unaligned");
d_unaligned = na;
}
void
block::set_is_unaligned(bool u)
{
d_is_unaligned = u;
}
void
block::set_relative_rate(double relative_rate)
{
if(relative_rate < 0.0)
throw std::invalid_argument("block::set_relative_rate");
d_relative_rate = relative_rate;
}
void
block::consume(int which_input, int how_many_items)
{
d_detail->consume(which_input, how_many_items);
}
void
block::consume_each(int how_many_items)
{
d_detail->consume_each(how_many_items);
}
void
block::produce(int which_output, int how_many_items)
{
d_detail->produce(which_output, how_many_items);
}
int
block::fixed_rate_ninput_to_noutput(int ninput)
{
throw std::runtime_error("Unimplemented");
}
int
block::fixed_rate_noutput_to_ninput(int noutput)
{
throw std::runtime_error("Unimplemented");
}
uint64_t
block::nitems_read(unsigned int which_input)
{
if(d_detail) {
return d_detail->nitems_read(which_input);
}
else {
//throw std::runtime_error("No block_detail associated with block yet");
return 0;
}
}
uint64_t
block::nitems_written(unsigned int which_output)
{
if(d_detail) {
return d_detail->nitems_written(which_output);
}
else {
//throw std::runtime_error("No block_detail associated with block yet");
return 0;
}
}
int
block::max_noutput_items()
{
return d_max_noutput_items;
}
void
block::set_max_noutput_items(int m)
{
if(m <= 0)
throw std::runtime_error("block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n");
d_max_noutput_items = m;
d_max_noutput_items_set = true;
}
void
block::unset_max_noutput_items()
{
d_max_noutput_items_set = false;
}
bool
block::is_set_max_noutput_items()
{
return d_max_noutput_items_set;
}
void
block::set_processor_affinity(const std::vector<int> &mask)
{
d_affinity = mask;
if(d_detail) {
d_detail->set_processor_affinity(d_affinity);
}
}
void
block::unset_processor_affinity()
{
d_affinity.clear();
if(d_detail) {
d_detail->unset_processor_affinity();
}
}
int
block::active_thread_priority()
{
if(d_detail) {
return d_detail->thread_priority();
}
return -1;
}
int
block::thread_priority()
{
return d_priority;
}
int
block::set_thread_priority(int priority)
{
d_priority = priority;
if(d_detail) {
return d_detail->set_thread_priority(priority);
}
return d_priority;
}
void
block::expand_minmax_buffer(int port)
{
if((size_t)port >= d_max_output_buffer.size())
set_max_output_buffer(port, -1);
if((size_t)port >= d_min_output_buffer.size())
set_min_output_buffer(port, -1);
}
long
block::max_output_buffer(size_t i)
{
if(i >= d_max_output_buffer.size())
throw std::invalid_argument("basic_block::max_output_buffer: port out of range.");
return d_max_output_buffer[i];
}
void
block::set_max_output_buffer(long max_output_buffer)
{
for(int i = 0; i < output_signature()->max_streams(); i++) {
set_max_output_buffer(i, max_output_buffer);
}
}
void
block::set_max_output_buffer(int port, long max_output_buffer)
{
if((size_t)port >= d_max_output_buffer.size())
d_max_output_buffer.push_back(max_output_buffer);
else
d_max_output_buffer[port] = max_output_buffer;
}
long
block::min_output_buffer(size_t i)
{
if(i >= d_min_output_buffer.size())
throw std::invalid_argument("basic_block::min_output_buffer: port out of range.");
return d_min_output_buffer[i];
}
void
block::set_min_output_buffer(long min_output_buffer)
{
std::cout << "set_min_output_buffer on block " << unique_id() << " to " << min_output_buffer << std::endl;
for(int i=0; i<output_signature()->max_streams(); i++) {
set_min_output_buffer(i, min_output_buffer);
}
}
void
block::set_min_output_buffer(int port, long min_output_buffer)
{
if((size_t)port >= d_min_output_buffer.size())
d_min_output_buffer.push_back(min_output_buffer);
else
d_min_output_buffer[port] = min_output_buffer;
}
float
block::pc_noutput_items()
{
if(d_detail) {
return d_detail->pc_noutput_items();
}
else {
return 0;
}
}
float
block::pc_noutput_items_avg()
{
if(d_detail) {
return d_detail->pc_noutput_items_avg();
}
else {
return 0;
}
}
float
block::pc_noutput_items_var()
{
if(d_detail) {
return d_detail->pc_noutput_items_var();
}
else {
return 0;
}
}
float
block::pc_nproduced()
{
if(d_detail) {
return d_detail->pc_nproduced();
}
else {
return 0;
}
}
float
block::pc_nproduced_avg()
{
if(d_detail) {
return d_detail->pc_nproduced_avg();
}
else {
return 0;
}
}
float
block::pc_nproduced_var()
{
if(d_detail) {
return d_detail->pc_nproduced_var();
}
else {
return 0;
}
}
float
block::pc_input_buffers_full(int which)
{
if(d_detail) {
return d_detail->pc_input_buffers_full(static_cast<size_t>(which));
}
else {
return 0;
}
}
float
block::pc_input_buffers_full_avg(int which)
{
if(d_detail) {
return d_detail->pc_input_buffers_full_avg(static_cast<size_t>(which));
}
else {
return 0;
}
}
float
block::pc_input_buffers_full_var(int which)
{
if(d_detail) {
return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which));
}
else {
return 0;
}
}
std::vector<float>
block::pc_input_buffers_full()
{
if(d_detail) {
return d_detail->pc_input_buffers_full();
}
else {
return std::vector<float>(1,0);
}
}
std::vector<float>
block::pc_input_buffers_full_avg()
{
if(d_detail) {
return d_detail->pc_input_buffers_full_avg();
}
else {
return std::vector<float>(1,0);
}
}
std::vector<float>
block::pc_input_buffers_full_var()
{
if(d_detail) {
return d_detail->pc_input_buffers_full_var();
}
else {
return std::vector<float>(1,0);
}
}
float
block::pc_output_buffers_full(int which)
{
if(d_detail) {
return d_detail->pc_output_buffers_full(static_cast<size_t>(which));
}
else {
return 0;
}
}
float
block::pc_output_buffers_full_avg(int which)
{
if(d_detail) {
return d_detail->pc_output_buffers_full_avg(static_cast<size_t>(which));
}
else {
return 0;
}
}
float
block::pc_output_buffers_full_var(int which)
{
if(d_detail) {
return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which));
}
else {
return 0;
}
}
std::vector<float>
block::pc_output_buffers_full()
{
if(d_detail) {
return d_detail->pc_output_buffers_full();
}
else {
return std::vector<float>(1,0);
}
}
std::vector<float>
block::pc_output_buffers_full_avg()
{
if(d_detail) {
return d_detail->pc_output_buffers_full_avg();
}
else {
return std::vector<float>(1,0);
}
}
std::vector<float>
block::pc_output_buffers_full_var()
{
if(d_detail) {
return d_detail->pc_output_buffers_full_var();
}
else {
return std::vector<float>(1,0);
}
}
float
block::pc_work_time()
{
if(d_detail) {
return d_detail->pc_work_time();
}
else {
return 0;
}
}
float
block::pc_work_time_avg()
{
if(d_detail) {
return d_detail->pc_work_time_avg();
}
else {
return 0;
}
}
float
block::pc_work_time_var()
{
if(d_detail) {
return d_detail->pc_work_time_var();
}
else {
return 0;
}
}
void
block::reset_perf_counters()
{
if(d_detail) {
d_detail->reset_perf_counters();
}
}
void
block::setup_pc_rpc()
{
d_pc_rpc_set = true;
}
std::ostream&
operator << (std::ostream& os, const block *m)
{
os << "<block " << m->name() << " (" << m->unique_id() << ")>";
return os;
}
int
block::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
throw std::runtime_error("block::general_work() not implemented");
return 0;
}
} /* namespace gr */

435
lib/runtime/block_detail.cc Normal file
View File

@ -0,0 +1,435 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/block_detail.h>
#include <gnuradio/buffer.h>
#include <iostream>
namespace gr {
static long s_ncurrently_allocated = 0;
long
block_detail_ncurrently_allocated()
{
return s_ncurrently_allocated;
}
block_detail::block_detail(unsigned int ninputs, unsigned int noutputs)
: d_produce_or(0),
d_ninputs(ninputs), d_noutputs(noutputs),
d_input(ninputs), d_output(noutputs),
d_done(false),
d_ins_noutput_items(0),
d_avg_noutput_items(0),
d_var_noutput_items(0),
d_ins_nproduced(0),
d_avg_nproduced(0),
d_var_nproduced(0),
d_ins_input_buffers_full(ninputs, 0),
d_avg_input_buffers_full(ninputs, 0),
d_var_input_buffers_full(ninputs, 0),
d_ins_output_buffers_full(noutputs, 0),
d_avg_output_buffers_full(noutputs, 0),
d_var_output_buffers_full(noutputs, 0),
d_ins_work_time(0),
d_avg_work_time(0),
d_var_work_time(0),
d_pc_counter(0)
{
s_ncurrently_allocated++;
}
block_detail::~block_detail()
{
// should take care of itself
s_ncurrently_allocated--;
}
void
block_detail::set_input(unsigned int which, buffer_reader_sptr reader)
{
if(which >= d_ninputs)
throw std::invalid_argument("block_detail::set_input");
d_input[which] = reader;
}
void
block_detail::set_output(unsigned int which, buffer_sptr buffer)
{
if(which >= d_noutputs)
throw std::invalid_argument("block_detail::set_output");
d_output[which] = buffer;
}
block_detail_sptr
make_block_detail(unsigned int ninputs, unsigned int noutputs)
{
return block_detail_sptr (new block_detail(ninputs, noutputs));
}
void
block_detail::set_done(bool done)
{
d_done = done;
for(unsigned int i = 0; i < d_noutputs; i++)
d_output[i]->set_done(done);
for(unsigned int i = 0; i < d_ninputs; i++)
d_input[i]->set_done(done);
}
void
block_detail::consume(int which_input, int how_many_items)
{
if(how_many_items > 0) {
input(which_input)->update_read_pointer(how_many_items);
}
}
void
block_detail::consume_each(int how_many_items)
{
if(how_many_items > 0) {
for(int i = 0; i < ninputs (); i++) {
d_input[i]->update_read_pointer(how_many_items);
}
}
}
void
block_detail::produce(int which_output, int how_many_items)
{
if(how_many_items > 0) {
d_output[which_output]->update_write_pointer(how_many_items);
d_produce_or |= how_many_items;
}
}
void
block_detail::produce_each(int how_many_items)
{
if(how_many_items > 0) {
for(int i = 0; i < noutputs (); i++) {
d_output[i]->update_write_pointer (how_many_items);
}
d_produce_or |= how_many_items;
}
}
uint64_t
block_detail::nitems_read(unsigned int which_input)
{
if(which_input >= d_ninputs)
throw std::invalid_argument ("block_detail::n_input_items");
return d_input[which_input]->nitems_read();
}
uint64_t
block_detail::nitems_written(unsigned int which_output)
{
if(which_output >= d_noutputs)
throw std::invalid_argument ("block_detail::n_output_items");
return d_output[which_output]->nitems_written();
}
void
block_detail::set_processor_affinity(const std::vector<int> &mask)
{
if(threaded) {
try {
gr::thread::thread_bind_to_processor(thread, mask);
}
catch (std::runtime_error e) {
std::cerr << "set_processor_affinity: invalid mask." << std::endl;;
}
}
}
void
block_detail::unset_processor_affinity()
{
if(threaded) {
gr::thread::thread_unbind(thread);
}
}
int
block_detail::thread_priority(){
if(threaded) {
return gr::thread::thread_priority(thread);
}
return -1;
}
int
block_detail::set_thread_priority(int priority){
if(threaded) {
return gr::thread::set_thread_priority(thread,priority);
}
return -1;
}
void
block_detail::start_perf_counters()
{
d_start_of_work = gr::high_res_timer_now_perfmon();
}
void
block_detail::stop_perf_counters(int noutput_items, int nproduced)
{
d_end_of_work = gr::high_res_timer_now_perfmon();
gr::high_res_timer_type diff = d_end_of_work - d_start_of_work;
if(d_pc_counter == 0) {
d_ins_work_time = diff;
d_avg_work_time = diff;
d_var_work_time = 0;
d_ins_nproduced = nproduced;
d_avg_nproduced = nproduced;
d_var_nproduced = 0;
d_ins_noutput_items = noutput_items;
d_avg_noutput_items = noutput_items;
d_var_noutput_items = 0;
for(size_t i=0; i < d_input.size(); i++) {
gr::thread::scoped_lock guard(*d_input[i]->mutex());
float pfull = static_cast<float>(d_input[i]->items_available()) /
static_cast<float>(d_input[i]->max_possible_items_available());
d_ins_input_buffers_full[i] = pfull;
d_avg_input_buffers_full[i] = pfull;
d_var_input_buffers_full[i] = 0;
}
for(size_t i=0; i < d_output.size(); i++) {
gr::thread::scoped_lock guard(*d_output[i]->mutex());
float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
static_cast<float>(d_output[i]->bufsize());
d_ins_output_buffers_full[i] = pfull;
d_avg_output_buffers_full[i] = pfull;
d_var_output_buffers_full[i] = 0;
}
}
else {
float d = diff - d_avg_work_time;
d_ins_work_time = diff;
d_avg_work_time = d_avg_work_time + d/d_pc_counter;
d_var_work_time = d_var_work_time + d*d;
d = nproduced - d_avg_nproduced;
d_ins_nproduced = nproduced;
d_avg_nproduced = d_avg_nproduced + d/d_pc_counter;
d_var_nproduced = d_var_nproduced + d*d;
d = noutput_items - d_avg_noutput_items;
d_ins_noutput_items = noutput_items;
d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter;
d_var_noutput_items = d_var_noutput_items + d*d;
for(size_t i=0; i < d_input.size(); i++) {
gr::thread::scoped_lock guard(*d_input[i]->mutex());
float pfull = static_cast<float>(d_input[i]->items_available()) /
static_cast<float>(d_input[i]->max_possible_items_available());
d = pfull - d_avg_input_buffers_full[i];
d_ins_input_buffers_full[i] = pfull;
d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter;
d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d;
}
for(size_t i=0; i < d_output.size(); i++) {
gr::thread::scoped_lock guard(*d_output[i]->mutex());
float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
static_cast<float>(d_output[i]->bufsize());
d = pfull - d_avg_output_buffers_full[i];
d_ins_output_buffers_full[i] = pfull;
d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter;
d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d;
}
}
d_pc_counter++;
}
void
block_detail::reset_perf_counters()
{
d_pc_counter = 0;
}
float
block_detail::pc_noutput_items()
{
return d_ins_noutput_items;
}
float
block_detail::pc_nproduced()
{
return d_ins_nproduced;
}
float
block_detail::pc_input_buffers_full(size_t which)
{
if(which < d_ins_input_buffers_full.size())
return d_ins_input_buffers_full[which];
else
return 0;
}
std::vector<float>
block_detail::pc_input_buffers_full()
{
return d_ins_input_buffers_full;
}
float
block_detail::pc_output_buffers_full(size_t which)
{
if(which < d_ins_output_buffers_full.size())
return d_ins_output_buffers_full[which];
else
return 0;
}
std::vector<float>
block_detail::pc_output_buffers_full()
{
return d_ins_output_buffers_full;
}
float
block_detail::pc_work_time()
{
return d_ins_work_time;
}
float
block_detail::pc_noutput_items_avg()
{
return d_avg_noutput_items;
}
float
block_detail::pc_nproduced_avg()
{
return d_avg_nproduced;
}
float
block_detail::pc_input_buffers_full_avg(size_t which)
{
if(which < d_avg_input_buffers_full.size())
return d_avg_input_buffers_full[which];
else
return 0;
}
std::vector<float>
block_detail::pc_input_buffers_full_avg()
{
return d_avg_input_buffers_full;
}
float
block_detail::pc_output_buffers_full_avg(size_t which)
{
if(which < d_avg_output_buffers_full.size())
return d_avg_output_buffers_full[which];
else
return 0;
}
std::vector<float>
block_detail::pc_output_buffers_full_avg()
{
return d_avg_output_buffers_full;
}
float
block_detail::pc_work_time_avg()
{
return d_avg_work_time;
}
float
block_detail::pc_noutput_items_var()
{
return d_var_noutput_items/(d_pc_counter-1);
}
float
block_detail::pc_nproduced_var()
{
return d_var_nproduced/(d_pc_counter-1);
}
float
block_detail::pc_input_buffers_full_var(size_t which)
{
if(which < d_avg_input_buffers_full.size())
return d_var_input_buffers_full[which]/(d_pc_counter-1);
else
return 0;
}
std::vector<float>
block_detail::pc_input_buffers_full_var()
{
std::vector<float> var(d_avg_input_buffers_full.size(), 0);
for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++)
var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1);
return var;
}
float
block_detail::pc_output_buffers_full_var(size_t which)
{
if(which < d_avg_output_buffers_full.size())
return d_var_output_buffers_full[which]/(d_pc_counter-1);
else
return 0;
}
std::vector<float>
block_detail::pc_output_buffers_full_var()
{
std::vector<float> var(d_avg_output_buffers_full.size(), 0);
for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++)
var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1);
return var;
}
float
block_detail::pc_work_time_var()
{
return d_var_work_time/(d_pc_counter-1);
}
} /* namespace gr */

View File

@ -0,0 +1,419 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2008-2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <block_executor.h>
#include <gnuradio/block.h>
#include <gnuradio/block_detail.h>
#include <gnuradio/buffer.h>
#include <gnuradio/prefs.h>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
#include <limits>
#include <assert.h>
#include <stdio.h>
namespace gr {
// must be defined to either 0 or 1
#define ENABLE_LOGGING 0
#if (ENABLE_LOGGING)
#define LOG(x) do { x; } while(0)
#else
#define LOG(x) do {;} while(0)
#endif
static int which_scheduler = 0;
inline static unsigned int
round_up(unsigned int n, unsigned int multiple)
{
return ((n + multiple - 1) / multiple) * multiple;
}
inline static unsigned int
round_down(unsigned int n, unsigned int multiple)
{
return (n / multiple) * multiple;
}
//
// Return minimum available write space in all our downstream
// buffers or -1 if we're output blocked and the output we're
// blocked on is done.
//
static int
min_available_space(block_detail *d, int output_multiple, int min_noutput_items)
{
int min_space = std::numeric_limits<int>::max();
if(min_noutput_items == 0)
min_noutput_items = 1;
for(int i = 0; i < d->noutputs (); i++) {
gr::thread::scoped_lock guard(*d->output(i)->mutex());
int avail_n = round_down(d->output(i)->space_available(), output_multiple);
int best_n = round_down(d->output(i)->bufsize()/2, output_multiple);
if(best_n < min_noutput_items)
throw std::runtime_error("Buffer too small for min_noutput_items");
int n = std::min(avail_n, best_n);
if(n < min_noutput_items){ // We're blocked on output.
if(d->output(i)->done()){ // Downstream is done, therefore we're done.
return -1;
}
return 0;
}
min_space = std::min(min_space, n);
}
return min_space;
}
block_executor::block_executor(block_sptr block, int max_noutput_items)
: d_block(block), d_log(0), d_max_noutput_items(max_noutput_items)
{
if(ENABLE_LOGGING) {
std::string name = str(boost::format("sst-%03d.log") % which_scheduler++);
d_log = new std::ofstream(name.c_str());
std::unitbuf(*d_log); // make it unbuffered...
*d_log << "block_executor: "
<< d_block << std::endl;
}
#ifdef GR_PERFORMANCE_COUNTERS
prefs *prefs = prefs::singleton();
d_use_pc = prefs->get_bool("PerfCounters", "on", false);
#endif /* GR_PERFORMANCE_COUNTERS */
d_block->start(); // enable any drivers, etc.
}
block_executor::~block_executor()
{
if(ENABLE_LOGGING)
delete d_log;
d_block->stop(); // stop any drivers, etc.
}
block_executor::state
block_executor::run_one_iteration()
{
int noutput_items;
int max_items_avail;
int max_noutput_items;
int new_alignment = 0;
int alignment_state = -1;
block *m = d_block.get();
block_detail *d = m->detail().get();
LOG(*d_log << std::endl << m);
max_noutput_items = round_down(d_max_noutput_items, m->output_multiple());
if(d->done()){
assert(0);
return DONE;
}
if(d->source_p ()) {
d_ninput_items_required.resize(0);
d_ninput_items.resize(0);
d_input_items.resize(0);
d_input_done.resize(0);
d_output_items.resize(d->noutputs());
d_start_nitems_read.resize(0);
// determine the minimum available output space
noutput_items = min_available_space(d, m->output_multiple (), m->min_noutput_items ());
noutput_items = std::min(noutput_items, max_noutput_items);
LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
if(noutput_items == -1) // we're done
goto were_done;
if(noutput_items == 0){ // we're output blocked
LOG(*d_log << " BLKD_OUT\n");
return BLKD_OUT;
}
goto setup_call_to_work; // jump to common code
}
else if(d->sink_p ()) {
d_ninput_items_required.resize(d->ninputs ());
d_ninput_items.resize(d->ninputs ());
d_input_items.resize(d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (0);
d_start_nitems_read.resize(d->ninputs());
LOG(*d_log << " sink\n");
max_items_avail = 0;
for(int i = 0; i < d->ninputs (); i++) {
{
/*
* Acquire the mutex and grab local copies of items_available and done.
*/
gr::thread::scoped_lock guard(*d->input(i)->mutex());
d_ninput_items[i] = d->input(i)->items_available();
d_input_done[i] = d->input(i)->done();
}
LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl);
LOG(*d_log << " d_input_done[" << i << "] = " << d_input_done[i] << std::endl);
if (d_ninput_items[i] < m->output_multiple() && d_input_done[i])
goto were_done;
max_items_avail = std::max (max_items_avail, d_ninput_items[i]);
}
// take a swag at how much output we can sink
noutput_items = (int)(max_items_avail * m->relative_rate ());
noutput_items = round_down(noutput_items, m->output_multiple ());
noutput_items = std::min(noutput_items, max_noutput_items);
LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl);
LOG(*d_log << " noutput_items = " << noutput_items << std::endl);
if(noutput_items == 0) { // we're blocked on input
LOG(*d_log << " BLKD_IN\n");
return BLKD_IN;
}
goto try_again; // Jump to code shared with regular case.
}
else {
// do the regular thing
d_ninput_items_required.resize (d->ninputs ());
d_ninput_items.resize (d->ninputs ());
d_input_items.resize (d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (d->noutputs ());
d_start_nitems_read.resize(d->ninputs());
max_items_avail = 0;
for(int i = 0; i < d->ninputs (); i++) {
{
/*
* Acquire the mutex and grab local copies of items_available and done.
*/
gr::thread::scoped_lock guard(*d->input(i)->mutex());
d_ninput_items[i] = d->input(i)->items_available ();
d_input_done[i] = d->input(i)->done();
}
max_items_avail = std::max(max_items_avail, d_ninput_items[i]);
}
// determine the minimum available output space
noutput_items = min_available_space(d, m->output_multiple(), m->min_noutput_items());
if(ENABLE_LOGGING) {
*d_log << " regular ";
if(m->relative_rate() >= 1.0)
*d_log << "1:" << m->relative_rate() << std::endl;
else
*d_log << 1.0/m->relative_rate() << ":1\n";
*d_log << " max_items_avail = " << max_items_avail << std::endl;
*d_log << " noutput_items = " << noutput_items << std::endl;
}
if(noutput_items == -1) // we're done
goto were_done;
if(noutput_items == 0) { // we're output blocked
LOG(*d_log << " BLKD_OUT\n");
return BLKD_OUT;
}
try_again:
if(m->fixed_rate()) {
// try to work it forward starting with max_items_avail.
// We want to try to consume all the input we've got.
int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail);
// only test this if we specifically set the output_multiple
if(m->output_multiple_set())
reqd_noutput_items = round_down(reqd_noutput_items, m->output_multiple());
if(reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items)
noutput_items = reqd_noutput_items;
// if we need this many outputs, overrule the max_noutput_items setting
max_noutput_items = std::max(m->output_multiple(), max_noutput_items);
}
noutput_items = std::min(noutput_items, max_noutput_items);
// Check if we're still unaligned; use up items until we're
// aligned again. Otherwise, make sure we set the alignment
// requirement.
if(!m->output_multiple_set()) {
if(m->is_unaligned()) {
// When unaligned, don't just set noutput_items to the remaining
// samples to meet alignment; this causes too much overhead in
// requiring a premature call back here. Set the maximum amount
// of samples to handle unalignment and get us back aligned.
if(noutput_items >= m->unaligned()) {
noutput_items = round_up(noutput_items, m->alignment()) \
- (m->alignment() - m->unaligned());
new_alignment = 0;
}
else {
new_alignment = m->unaligned() - noutput_items;
}
alignment_state = 0;
}
else if(noutput_items < m->alignment()) {
// if we don't have enough for an aligned call, keep track of
// misalignment, set unaligned flag, and proceed.
new_alignment = m->alignment() - noutput_items;
m->set_unaligned(new_alignment);
m->set_is_unaligned(true);
alignment_state = 1;
}
else {
// enough to round down to the nearest alignment and process.
noutput_items = round_down(noutput_items, m->alignment());
m->set_is_unaligned(false);
alignment_state = 2;
}
}
// ask the block how much input they need to produce noutput_items
m->forecast (noutput_items, d_ninput_items_required);
// See if we've got sufficient input available
int i;
for(i = 0; i < d->ninputs (); i++)
if(d_ninput_items_required[i] > d_ninput_items[i]) // not enough
break;
if(i < d->ninputs()) { // not enough input on input[i]
// if we can, try reducing the size of our output request
if(noutput_items > m->output_multiple()) {
noutput_items /= 2;
noutput_items = round_up(noutput_items, m->output_multiple());
goto try_again;
}
// We're blocked on input
LOG(*d_log << " BLKD_IN\n");
if(d_input_done[i]) // If the upstream block is done, we're done
goto were_done;
// Is it possible to ever fulfill this request?
if(d_ninput_items_required[i] > d->input(i)->max_possible_items_available()) {
// Nope, never going to happen...
std::cerr << "\nsched: <block " << m->name()
<< " (" << m->unique_id() << ")>"
<< " is requesting more input data\n"
<< " than we can provide.\n"
<< " ninput_items_required = "
<< d_ninput_items_required[i] << "\n"
<< " max_possible_items_available = "
<< d->input(i)->max_possible_items_available() << "\n"
<< " If this is a filter, consider reducing the number of taps.\n";
goto were_done;
}
// If we were made unaligned in this round but return here without
// processing; reset the unalignment claim before next entry.
if(alignment_state == 1) {
m->set_unaligned(0);
m->set_is_unaligned(false);
}
return BLKD_IN;
}
// We've got enough data on each input to produce noutput_items.
// Finish setting up the call to work.
for(int i = 0; i < d->ninputs (); i++)
d_input_items[i] = d->input(i)->read_pointer();
setup_call_to_work:
d->d_produce_or = 0;
for(int i = 0; i < d->noutputs (); i++)
d_output_items[i] = d->output(i)->write_pointer();
// determine where to start looking for new tags
for(int i = 0; i < d->ninputs(); i++)
d_start_nitems_read[i] = d->nitems_read(i);
#ifdef GR_PERFORMANCE_COUNTERS
if(d_use_pc)
d->start_perf_counters();
#endif /* GR_PERFORMANCE_COUNTERS */
// Do the actual work of the block
int n = m->general_work(noutput_items, d_ninput_items,
d_input_items, d_output_items);
#ifdef GR_PERFORMANCE_COUNTERS
if(d_use_pc)
d->stop_perf_counters(noutput_items, n);
#endif /* GR_PERFORMANCE_COUNTERS */
LOG(*d_log << " general_work: noutput_items = " << noutput_items
<< " result = " << n << std::endl);
// Adjust number of unaligned items left to process
if(m->is_unaligned()) {
m->set_unaligned(new_alignment);
m->set_is_unaligned(m->unaligned() != 0);
}
if(n == block::WORK_DONE)
goto were_done;
if(n != block::WORK_CALLED_PRODUCE)
d->produce_each (n); // advance write pointers
if(d->d_produce_or > 0) // block produced something
return READY;
// We didn't produce any output even though we called general_work.
// We have (most likely) consumed some input.
/*
// If this is a source, it's broken.
if(d->source_p()) {
std::cerr << "block_executor: source " << m
<< " produced no output. We're marking it DONE.\n";
// FIXME maybe we ought to raise an exception...
goto were_done;
}
*/
// Have the caller try again...
return READY_NO_OUTPUT;
}
assert(0);
were_done:
LOG(*d_log << " were_done\n");
d->set_done (true);
return DONE;
}
} /* namespace gr */

View File

@ -0,0 +1,77 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H
#define INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H
#include <gnuradio/api.h>
#include <gnuradio/runtime_types.h>
#include <fstream>
#include <stdint.h>
namespace gr {
/*!
* \brief Manage the execution of a single block.
* \ingroup internal
*/
class GR_RUNTIME_API block_executor
{
protected:
block_sptr d_block; // The block we're trying to run
std::ofstream *d_log;
// These are allocated here so we don't have to on each iteration
gr_vector_int d_ninput_items_required;
gr_vector_int d_ninput_items;
gr_vector_const_void_star d_input_items;
std::vector<bool> d_input_done;
gr_vector_void_star d_output_items;
std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work
int d_max_noutput_items;
#ifdef GR_PERFORMANCE_COUNTERS
bool d_use_pc;
#endif /* GR_PERFORMANCE_COUNTERS */
public:
block_executor(block_sptr block, int max_noutput_items=100000);
~block_executor();
enum state {
READY, // We made progress; everything's cool.
READY_NO_OUTPUT, // We consumed some input, but produced no output.
BLKD_IN, // no progress; we're blocked waiting for input data.
BLKD_OUT, // no progress; we're blocked waiting for output buffer space.
DONE, // we're done; don't call me again.
};
/*
* \brief Run one iteration.
*/
state run_one_iteration();
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H */

View File

@ -0,0 +1,186 @@
/*
* Copyright 2011-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "block_gateway_impl.h"
#include <gnuradio/io_signature.h>
#include <iostream>
#include <boost/bind.hpp>
namespace gr {
/***********************************************************************
* Helper routines
**********************************************************************/
template <typename OutType, typename InType>
void
copy_pointers(OutType &out, const InType &in)
{
out.resize(in.size());
for(size_t i = 0; i < in.size(); i++) {
out[i] = (void *)(in[i]);
}
}
block_gateway::sptr
block_gateway::make(feval_ll *handler,
const std::string &name,
gr::io_signature::sptr in_sig,
gr::io_signature::sptr out_sig,
const block_gw_work_type work_type,
const unsigned factor)
{
return block_gateway::sptr
(new block_gateway_impl(handler, name, in_sig, out_sig,
work_type, factor));
}
block_gateway_impl::block_gateway_impl(feval_ll *handler,
const std::string &name,
gr::io_signature::sptr in_sig,
gr::io_signature::sptr out_sig,
const block_gw_work_type work_type,
const unsigned factor)
: block(name, in_sig, out_sig),
_handler(handler),
_work_type(work_type)
{
switch(_work_type) {
case GR_BLOCK_GW_WORK_GENERAL:
_decim = 1; //not relevant, but set anyway
_interp = 1; //not relevant, but set anyway
break;
case GR_BLOCK_GW_WORK_SYNC:
_decim = 1;
_interp = 1;
this->set_fixed_rate(true);
break;
case GR_BLOCK_GW_WORK_DECIM:
_decim = factor;
_interp = 1;
break;
case GR_BLOCK_GW_WORK_INTERP:
_decim = 1;
_interp = factor;
this->set_output_multiple(_interp);
break;
}
}
void
block_gateway_impl::forecast(int noutput_items,
gr_vector_int &ninput_items_required)
{
switch(_work_type) {
case GR_BLOCK_GW_WORK_GENERAL:
_message.action = block_gw_message_type::ACTION_FORECAST;
_message.forecast_args_noutput_items = noutput_items;
_message.forecast_args_ninput_items_required = ninput_items_required;
_handler->calleval(0);
ninput_items_required = _message.forecast_args_ninput_items_required;
return;
default:
unsigned ninputs = ninput_items_required.size();
for(unsigned i = 0; i < ninputs; i++)
ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
return;
}
}
int
block_gateway_impl::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
switch(_work_type) {
case GR_BLOCK_GW_WORK_GENERAL:
_message.action = block_gw_message_type::ACTION_GENERAL_WORK;
_message.general_work_args_noutput_items = noutput_items;
_message.general_work_args_ninput_items = ninput_items;
copy_pointers(_message.general_work_args_input_items, input_items);
_message.general_work_args_output_items = output_items;
_handler->calleval(0);
return _message.general_work_args_return_value;
default:
int r = work (noutput_items, input_items, output_items);
if(r > 0)
consume_each(r*_decim/_interp);
return r;
}
}
int
block_gateway_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
_message.action = block_gw_message_type::ACTION_WORK;
_message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items);
if(_message.work_args_ninput_items == 0)
return -1;
_message.work_args_noutput_items = noutput_items;
copy_pointers(_message.work_args_input_items, input_items);
_message.work_args_output_items = output_items;
_handler->calleval(0);
return _message.work_args_return_value;
}
int
block_gateway_impl::fixed_rate_noutput_to_ninput(int noutput_items)
{
return (noutput_items*_decim/_interp) + history() - 1;
}
int
block_gateway_impl::fixed_rate_ninput_to_noutput(int ninput_items)
{
return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim;
}
bool
block_gateway_impl::start(void)
{
_message.action = block_gw_message_type::ACTION_START;
_handler->calleval(0);
return _message.start_args_return_value;
}
bool
block_gateway_impl::stop(void)
{
_message.action = block_gw_message_type::ACTION_STOP;
_handler->calleval(0);
return _message.stop_args_return_value;
}
block_gw_message_type&
block_gateway_impl::block_message(void)
{
return _message;
}
} /* namespace gr */

View File

@ -0,0 +1,75 @@
/* -*- c++ -*- */
/*
* Copyright 2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_IMPL_H
#define INCLUDED_RUNTIME_BLOCK_GATEWAY_IMPL_H
#include <gnuradio/block_gateway.h>
namespace gr {
/***********************************************************************
* The gr::block gateway implementation class
**********************************************************************/
class block_gateway_impl : public block_gateway
{
public:
block_gateway_impl(feval_ll *handler,
const std::string &name,
gr::io_signature::sptr in_sig,
gr::io_signature::sptr out_sig,
const block_gw_work_type work_type,
const unsigned factor);
/*******************************************************************
* Overloads for various scheduler-called functions
******************************************************************/
void forecast(int noutput_items,
gr_vector_int &ninput_items_required);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
int fixed_rate_noutput_to_ninput(int noutput_items);
int fixed_rate_ninput_to_noutput(int ninput_items);
bool start(void);
bool stop(void);
block_gw_message_type& block_message(void);
private:
feval_ll *_handler;
block_gw_message_type _message;
const block_gw_work_type _work_type;
unsigned _decim, _interp;
};
} /* namespace gr */
#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */

View File

@ -0,0 +1,111 @@
/* -*- c++ -*- */
/*
* Copyright 2012-2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <gnuradio/basic_block.h>
#include <gnuradio/block.h>
#include <gnuradio/block_detail.h>
#include <gnuradio/block_registry.h>
#include <gnuradio/tpb_detail.h>
#include <stdio.h>
gr::block_registry global_block_registry;
namespace gr {
block_registry::block_registry()
{
}
long
block_registry::block_register(basic_block* block)
{
gr::thread::scoped_lock guard(d_mutex);
if(d_map.find(block->name()) == d_map.end()) {
d_map[block->name()] = blocksubmap_t();
d_map[block->name()][0] = block;
return 0;
}
else {
for(size_t i=0; i<=d_map[block->name()].size(); i++){
if(d_map[block->name()].find(i) == d_map[block->name()].end()){
d_map[block->name()][i] = block;
return i;
}
}
}
throw std::runtime_error("should not reach this");
}
void
block_registry::block_unregister(basic_block* block)
{
gr::thread::scoped_lock guard(d_mutex);
d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id()));
}
std::string
block_registry::register_symbolic_name(basic_block* block)
{
std::stringstream ss;
ss << block->name() << block->symbolic_id();
//std::cout << "register_symbolic_name: " << ss.str() << std::endl;
register_symbolic_name(block, ss.str());
return ss.str();
}
void
block_registry::register_symbolic_name(basic_block* block, std::string name)
{
gr::thread::scoped_lock guard(d_mutex);
}
void
block_registry::register_primitive(std::string blk, block* ref)
{
gr::thread::scoped_lock guard(d_mutex);
primitive_map[blk] = ref;
}
void
block_registry::unregister_primitive(std::string blk)
{
gr::thread::scoped_lock guard(d_mutex);
primitive_map.erase(primitive_map.find(blk));
}
void
block_registry::notify_blk(std::string blk)
{
gr::thread::scoped_lock guard(d_mutex);
if(primitive_map.find(blk) == primitive_map.end()) {
return;
}
if(primitive_map[blk]->detail().get())
primitive_map[blk]->detail()->d_tpb.notify_msg();
}
} /* namespace gr */

View File

@ -0,0 +1,60 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "null_sink_impl.h"
#include <gnuradio/io_signature.h>
namespace gr {
namespace blocks {
null_sink::sptr
null_sink::make(size_t sizeof_stream_item)
{
return gnuradio::get_initial_sptr
(new null_sink_impl(sizeof_stream_item));
}
null_sink_impl::null_sink_impl(size_t sizeof_stream_item)
: sync_block("null_sink",
io_signature::make(1, 1, sizeof_stream_item),
io_signature::make(0, 0, 0))
{
}
null_sink_impl::~null_sink_impl()
{
}
int
null_sink_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
return noutput_items;
}
} /* namespace blocks */
} /* namespace gr */

View File

@ -0,0 +1,45 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_NULL_SINK_IMPL_H
#define INCLUDED_GR_NULL_SINK_IMPL_H
#include <gnuradio/blocks/null_sink.h>
namespace gr {
namespace blocks {
class null_sink_impl : public null_sink
{
public:
null_sink_impl(size_t sizeof_stream_item);
~null_sink_impl();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_NULL_SINK_IMPL_H */

View File

@ -0,0 +1,63 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "null_source_impl.h"
#include <gnuradio/io_signature.h>
#include <string.h>
namespace gr {
namespace blocks {
null_source::sptr
null_source::make(size_t sizeof_stream_item)
{
return gnuradio::get_initial_sptr
(new null_source_impl(sizeof_stream_item));
}
null_source_impl::null_source_impl (size_t sizeof_stream_item)
: sync_block("null_source",
io_signature::make(0, 0, 0),
io_signature::make(1, 1, sizeof_stream_item))
{
}
null_source_impl::~null_source_impl()
{
}
int
null_source_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
void *optr = (void*)output_items[0];
memset(optr, 0, noutput_items * output_signature()->sizeof_stream_item(0));
return noutput_items;
}
} /* namespace blocks */
} /* namespace gr */

View File

@ -0,0 +1,45 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_NULL_SOURCE_IMPL_H
#define INCLUDED_GR_NULL_SOURCE_IMPL_H
#include <gnuradio/blocks/null_source.h>
namespace gr {
namespace blocks {
class null_source_impl : public null_source
{
public:
null_source_impl(size_t sizeof_stream_item);
~null_source_impl();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_NULL_SOURCE_IMPL_H */

View File

@ -0,0 +1,102 @@
/* -*- c++ -*- */
/*
* Copyright 2005-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "throttle_impl.h"
#include <gnuradio/io_signature.h>
#include <cstring>
#include <boost/thread/thread.hpp>
namespace gr {
namespace blocks {
throttle::sptr
throttle::make(size_t itemsize, double samples_per_sec)
{
return gnuradio::get_initial_sptr
(new throttle_impl(itemsize, samples_per_sec));
}
throttle_impl::throttle_impl(size_t itemsize,
double samples_per_second)
: sync_block("throttle",
io_signature::make(1, 1, itemsize),
io_signature::make(1, 1, itemsize)),
d_itemsize(itemsize)
{
set_sample_rate(samples_per_second);
}
throttle_impl::~throttle_impl()
{
}
void
throttle_impl::set_sample_rate(double rate)
{
//changing the sample rate performs a reset of state params
d_start = boost::get_system_time();
d_total_samples = 0;
d_samps_per_tick = rate/boost::posix_time::time_duration::ticks_per_second();
d_samps_per_us = rate/1e6;
}
double
throttle_impl::sample_rate() const
{
return d_samps_per_us * 1e6;
}
int
throttle_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
//calculate the expected number of samples to have passed through
boost::system_time now = boost::get_system_time();
boost::int64_t ticks = (now - d_start).ticks();
uint64_t expected_samps = uint64_t(d_samps_per_tick*ticks);
//if the expected samples was less, we need to throttle back
if(d_total_samples > expected_samps) {
boost::this_thread::sleep(boost::posix_time::microseconds
(long((d_total_samples - expected_samps)/d_samps_per_us)));
}
//copy all samples output[i] <= input[i]
const char *in = (const char *)input_items[0];
char *out = (char *)output_items[0];
std::memcpy(out, in, noutput_items * d_itemsize);
d_total_samples += noutput_items;
return noutput_items;
}
void
throttle_impl::setup_rpc()
{
}
} /* namespace blocks */
} /* namespace gr */

View File

@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* Copyright 2005-2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_THROTTLE_IMPL_H
#define INCLUDED_GR_THROTTLE_IMPL_H
#include <gnuradio/blocks/throttle.h>
namespace gr {
namespace blocks {
class throttle_impl : public throttle
{
private:
boost::system_time d_start;
size_t d_itemsize;
uint64_t d_total_samples;
double d_samps_per_tick, d_samps_per_us;
public:
throttle_impl(size_t itemsize, double samples_per_sec);
~throttle_impl();
void setup_rpc();
void set_sample_rate(double rate);
double sample_rate() const;
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} /* namespace blocks */
} /* namespace gr */
#endif /* INCLUDED_GR_THROTTLE_IMPL_H */

269
lib/runtime/buffer.cc Normal file
View File

@ -0,0 +1,269 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/buffer.h>
#include <gnuradio/math.h>
#include "vmcircbuf.h"
#include <stdexcept>
#include <iostream>
#include <assert.h>
#include <algorithm>
#include <boost/math/common_factor_rt.hpp>
namespace gr {
static long s_buffer_count = 0; // counts for debugging storage mgmt
static long s_buffer_reader_count = 0;
/* ----------------------------------------------------------------------------
Notes on storage management
Pretty much all the fundamental classes are now using the
shared_ptr stuff for automatic reference counting. To ensure that
no mistakes are made, we make the constructors for classes private,
and then provide a free factory function that returns a smart
pointer to the desired class.
gr::buffer and gr::buffer_reader are no exceptions. However, they
both want pointers to each other, and unless we do something, we'll
never delete any of them because of the circular structure.
They'll always have a reference count of at least one. We could
use boost::weak_ptr's from gr::buffer to gr::buffer_reader but that
introduces it's own problems. (gr::buffer_reader's destructor needs
to call gr::buffer::drop_reader, but has no easy way to get a
shared_ptr to itself.)
Instead, we solve this problem by having gr::buffer hold a raw
pointer to gr::buffer_reader in its d_reader vector.
gr::buffer_reader's destructor calls gr::buffer::drop_reader, so
we're never left with an dangling pointer. gr::buffer_reader still
has a shared_ptr to the buffer ensuring that the buffer doesn't go
away under it. However, when the reference count of a
gr::buffer_reader goes to zero, we can successfully reclaim it.
---------------------------------------------------------------------------- */
/*
* Compute the minimum number of buffer items that work (i.e.,
* address space wrap-around works). To work is to satisfy this
* contraint for integer buffer_size and k:
*
* type_size * nitems == k * page_size
*/
static long
minimum_buffer_items(long type_size, long page_size)
{
return page_size / boost::math::gcd (type_size, page_size);
}
buffer::buffer(int nitems, size_t sizeof_item, block_sptr link)
: d_base(0), d_bufsize(0), d_vmcircbuf(0),
d_sizeof_item(sizeof_item), d_link(link),
d_write_index(0), d_abs_write_offset(0), d_done(false),
d_last_min_items_read(0)
{
if(!allocate_buffer (nitems, sizeof_item))
throw std::bad_alloc ();
s_buffer_count++;
}
buffer_sptr
make_buffer(int nitems, size_t sizeof_item, block_sptr link)
{
return buffer_sptr(new buffer(nitems, sizeof_item, link));
}
buffer::~buffer()
{
delete d_vmcircbuf;
assert(d_readers.size() == 0);
s_buffer_count--;
}
/*!
* sets d_vmcircbuf, d_base, d_bufsize.
* returns true iff successful.
*/
bool
buffer::allocate_buffer(int nitems, size_t sizeof_item)
{
int orig_nitems = nitems;
// Any buffersize we come up with must be a multiple of min_nitems.
int granularity = gr::vmcircbuf_sysconfig::granularity();
int min_nitems = minimum_buffer_items(sizeof_item, granularity);
// Round-up nitems to a multiple of min_nitems.
if(nitems % min_nitems != 0)
nitems = ((nitems / min_nitems) + 1) * min_nitems;
// If we rounded-up a whole bunch, give the user a heads up.
// This only happens if sizeof_item is not a power of two.
if(nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){
std::cerr << "gr::buffer::allocate_buffer: warning: tried to allocate\n"
<< " " << orig_nitems << " items of size "
<< sizeof_item << ". Due to alignment requirements\n"
<< " " << nitems << " were allocated. If this isn't OK, consider padding\n"
<< " your structure to a power-of-two bytes.\n"
<< " On this platform, our allocation granularity is " << granularity << " bytes.\n";
}
d_bufsize = nitems;
d_vmcircbuf = gr::vmcircbuf_sysconfig::make(d_bufsize * d_sizeof_item);
if(d_vmcircbuf == 0){
std::cerr << "gr::buffer::allocate_buffer: failed to allocate buffer of size "
<< d_bufsize * d_sizeof_item / 1024 << " KB\n";
return false;
}
d_base = (char*)d_vmcircbuf->pointer_to_first_copy();
return true;
}
int
buffer::space_available()
{
if(d_readers.empty())
return d_bufsize - 1; // See comment below
else {
// Find out the maximum amount of data available to our readers
int most_data = d_readers[0]->items_available();
uint64_t min_items_read = d_readers[0]->nitems_read();
for(size_t i = 1; i < d_readers.size (); i++) {
most_data = std::max(most_data, d_readers[i]->items_available());
min_items_read = std::min(min_items_read, d_readers[i]->nitems_read());
}
if(min_items_read != d_last_min_items_read) {
d_last_min_items_read = min_items_read;
}
// The -1 ensures that the case d_write_index == d_read_index is
// unambiguous. It indicates that there is no data for the reader
return d_bufsize - most_data - 1;
}
}
void *
buffer::write_pointer()
{
return &d_base[d_write_index * d_sizeof_item];
}
void
buffer::update_write_pointer(int nitems)
{
gr::thread::scoped_lock guard(*mutex());
d_write_index = index_add(d_write_index, nitems);
d_abs_write_offset += nitems;
}
void
buffer::set_done(bool done)
{
gr::thread::scoped_lock guard(*mutex());
d_done = done;
}
buffer_reader_sptr
buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link)
{
if(nzero_preload < 0)
throw std::invalid_argument("buffer_add_reader: nzero_preload must be >= 0");
buffer_reader_sptr r(new buffer_reader(buf,
buf->index_sub(buf->d_write_index,
nzero_preload),
link));
buf->d_readers.push_back(r.get ());
return r;
}
void
buffer::drop_reader(buffer_reader *reader)
{
std::vector<buffer_reader *>::iterator result =
std::find(d_readers.begin(), d_readers.end(), reader);
if(result == d_readers.end())
throw std::invalid_argument("buffer::drop_reader"); // we didn't find it...
d_readers.erase(result);
}
long
buffer_ncurrently_allocated()
{
return s_buffer_count;
}
// ----------------------------------------------------------------------------
buffer_reader::buffer_reader(buffer_sptr buffer, unsigned int read_index,
block_sptr link)
: d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link)
{
s_buffer_reader_count++;
}
buffer_reader::~buffer_reader()
{
d_buffer->drop_reader(this);
s_buffer_reader_count--;
}
int
buffer_reader::items_available() const
{
return d_buffer->index_sub(d_buffer->d_write_index, d_read_index);
}
const void *
buffer_reader::read_pointer()
{
return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item];
}
void
buffer_reader::update_read_pointer(int nitems)
{
gr::thread::scoped_lock guard(*mutex());
d_read_index = d_buffer->index_add (d_read_index, nitems);
d_abs_read_offset += nitems;
}
long
buffer_reader_ncurrently_allocated()
{
return s_buffer_reader_count;
}
} /* namespace gr */

View File

@ -0,0 +1,208 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "circular_file.h"
#include <unistd.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_IO_H
#include <io.h>
#endif
namespace gr {
static const int HEADER_SIZE = 4096;
static const int HEADER_MAGIC = 0xEB021026;
static const int HD_MAGIC = 0;
static const int HD_HEADER_SIZE = 1; // integer offsets into header
static const int HD_BUFFER_SIZE = 2;
static const int HD_BUFFER_BASE = 3;
static const int HD_BUFFER_CURRENT = 4;
circular_file::circular_file(const char *filename,
bool writable, int size)
: d_fd(-1), d_header(0), d_buffer(0), d_mapped_size(0), d_bytes_read(0)
{
int mm_prot;
if(writable) {
#ifdef HAVE_MMAP
mm_prot = PROT_READ | PROT_WRITE;
#endif
d_fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0664);
if(d_fd < 0) {
perror(filename);
exit(1);
}
#ifdef HAVE_MMAP /* FIXME */
if(ftruncate(d_fd, size + HEADER_SIZE) != 0) {
perror(filename);
exit(1);
}
#endif
}
else {
#ifdef HAVE_MMAP
mm_prot = PROT_READ;
#endif
d_fd = open (filename, O_RDONLY);
if(d_fd < 0) {
perror(filename);
exit(1);
}
}
struct stat statbuf;
if(fstat (d_fd, &statbuf) < 0) {
perror(filename);
exit(1);
}
if(statbuf.st_size < HEADER_SIZE) {
fprintf(stderr, "%s: file too small to be circular buffer\n", filename);
exit(1);
}
d_mapped_size = statbuf.st_size;
#ifdef HAVE_MMAP
void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0);
if(p == MAP_FAILED) {
perror("gr::circular_file: mmap failed");
exit(1);
}
d_header = (int*)p;
#else
perror("gr::circular_file: mmap unsupported by this system");
exit(1);
#endif
if(writable) { // init header
if(size < 0) {
fprintf(stderr, "gr::circular_buffer: size must be > 0 when writable\n");
exit(1);
}
d_header[HD_MAGIC] = HEADER_MAGIC;
d_header[HD_HEADER_SIZE] = HEADER_SIZE;
d_header[HD_BUFFER_SIZE] = size;
d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header
d_header[HD_BUFFER_CURRENT] = 0;
}
// sanity check (the asserts are a bit unforgiving...)
assert(d_header[HD_MAGIC] == HEADER_MAGIC);
assert(d_header[HD_HEADER_SIZE] == HEADER_SIZE);
assert(d_header[HD_BUFFER_SIZE] > 0);
assert(d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]);
assert(d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size);
assert(d_header[HD_BUFFER_CURRENT] >= 0 &&
d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]);
d_bytes_read = 0;
d_buffer = (unsigned char*)d_header + d_header[HD_BUFFER_BASE];
}
circular_file::~circular_file()
{
#ifdef HAVE_MMAP
if(munmap ((char *) d_header, d_mapped_size) < 0) {
perror("gr::circular_file: munmap");
exit(1);
}
#endif
close(d_fd);
}
bool
circular_file::write(void *vdata, int nbytes)
{
unsigned char *data = (unsigned char*)vdata;
int buffer_size = d_header[HD_BUFFER_SIZE];
int buffer_current = d_header[HD_BUFFER_CURRENT];
while(nbytes > 0) {
int n = std::min(nbytes, buffer_size - buffer_current);
memcpy(d_buffer + buffer_current, data, n);
buffer_current += n;
if(buffer_current >= buffer_size)
buffer_current = 0;
data += n;
nbytes -= n;
}
d_header[HD_BUFFER_CURRENT] = buffer_current;
return true;
}
int
circular_file::read(void *vdata, int nbytes)
{
unsigned char *data = (unsigned char *) vdata;
int buffer_current = d_header[HD_BUFFER_CURRENT];
int buffer_size = d_header[HD_BUFFER_SIZE];
int total = 0;
nbytes = std::min(nbytes, buffer_size - d_bytes_read);
while(nbytes > 0) {
int offset = (buffer_current + d_bytes_read) % buffer_size;
int n = std::min (nbytes, buffer_size - offset);
memcpy(data, d_buffer + offset, n);
data += n;
d_bytes_read += n;
total += n;
nbytes -= n;
}
return total;
}
void
circular_file::reset_read_pointer()
{
d_bytes_read = 0;
}
} /* namespace gr */

View File

@ -0,0 +1,65 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef GR_CIRCULAR_FILE_H
#define GR_CIRCULAR_FILE_H
#include <gnuradio/api.h>
namespace gr {
/*
* writes input data into a circular buffer on disk.
*
* the file contains a fixed header:
* 0x0000: int32 magic (0xEB021026)
* 0x0004: int32 size in bytes of header (constant 4096)
* 0x0008: int32 size in bytes of circular buffer (not including header)
* 0x000C: int32 file offset to beginning of circular buffer
* 0x0010: int32 byte offset from beginning of circular buffer to
* current start of data
*/
class GR_RUNTIME_API circular_file
{
private:
int d_fd;
int *d_header;
unsigned char *d_buffer;
int d_mapped_size;
int d_bytes_read;
public:
circular_file(const char *filename, bool writable = false, int size = 0);
~circular_file();
bool write(void *data, int nbytes);
// returns # of bytes actually read or 0 if end of buffer, or -1 on error.
int read(void *data, int nbytes);
// reset read pointer to beginning of buffer.
void reset_read_pointer();
};
} /* namespace gr */
#endif /* GR_CIRCULAR_FILE_H */

View File

@ -0,0 +1,61 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnuradio/constants.h>
namespace gr {
const std::string
prefix()
{
return "@prefix@";
}
const std::string
sysconfdir()
{
return "@SYSCONFDIR@";
}
const std::string
prefsdir()
{
return "@GR_PREFSDIR@";
}
const std::string
build_date()
{
return "@BUILD_DATE@";
}
const std::string
version()
{
return "@GR_VERSION@";
}
} /* namespace gr */

136
lib/runtime/feval.cc Normal file
View File

@ -0,0 +1,136 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnuradio/feval.h>
namespace gr {
feval_dd::~feval_dd(){}
double
feval_dd::eval(double x)
{
return 0;
}
double
feval_dd::calleval(double x)
{
return eval(x);
}
// ----------------------------------------------------------------
feval_cc::~feval_cc(){}
gr_complex
feval_cc::eval(gr_complex x)
{
return 0;
}
gr_complex
feval_cc::calleval(gr_complex x)
{
return eval(x);
}
// ----------------------------------------------------------------
feval_ll::~feval_ll(){}
long
feval_ll::eval(long x)
{
return 0;
}
long
feval_ll::calleval(long x)
{
return eval(x);
}
// ----------------------------------------------------------------
feval::~feval(){}
void
feval::eval(void)
{
// nop
}
void
feval::calleval(void)
{
eval();
}
// ----------------------------------------------------------------
feval_p::~feval_p(){}
void
feval_p::eval(double x)
{
// nop
}
void
feval_p::calleval(double x)
{
eval(x);
}
/*
* Trivial examples showing C++ (transparently) calling Python
*/
double
feval_dd_example(feval_dd *f, double x)
{
return f->calleval(x);
}
gr_complex
feval_cc_example(feval_cc *f, gr_complex x)
{
return f->calleval(x);
}
long
feval_ll_example(feval_ll *f, long x)
{
return f->calleval(x);
}
void
feval_example(feval *f)
{
f->calleval();
}
} /* namespace gr */

View File

@ -0,0 +1,389 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "flat_flowgraph.h"
#include <gnuradio/block_detail.h>
#include <gnuradio/buffer.h>
#include <gnuradio/prefs.h>
//#include <volk/volk.h> // FIXME:
#include <iostream>
#include <map>
#include <boost/format.hpp>
namespace gr {
#define FLAT_FLOWGRAPH_DEBUG 0
// 32Kbyte buffer size between blocks
#define GR_FIXED_BUFFER_SIZE (32*(1L<<10))
static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
flat_flowgraph_sptr
make_flat_flowgraph()
{
return flat_flowgraph_sptr(new flat_flowgraph());
}
flat_flowgraph::flat_flowgraph()
{
}
flat_flowgraph::~flat_flowgraph()
{
}
void
flat_flowgraph::setup_connections()
{
basic_block_vector_t blocks = calc_used_blocks();
// Assign block details to blocks
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
cast_to_block_sptr(*p)->set_detail(allocate_block_detail(*p));
// Connect inputs to outputs for each block
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
connect_block_inputs(*p);
block_sptr block = cast_to_block_sptr(*p);
block->set_unaligned(0);
block->set_is_unaligned(false);
}
}
block_detail_sptr
flat_flowgraph::allocate_block_detail(basic_block_sptr block)
{
int ninputs = calc_used_ports(block, true).size();
int noutputs = calc_used_ports(block, false).size();
block_detail_sptr detail = make_block_detail(ninputs, noutputs);
block_sptr grblock = cast_to_block_sptr(block);
if(!grblock)
throw std::runtime_error("allocate_block_detail found non-gr::block");
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "Creating block detail for " << block << std::endl;
for(int i = 0; i < noutputs; i++) {
grblock->expand_minmax_buffer(i);
buffer_sptr buffer = allocate_buffer(block, i);
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "Allocated buffer for output " << block << ":" << i << std::endl;
detail->set_output(i, buffer);
// Update the block's max_output_buffer based on what was actually allocated.
grblock->set_max_output_buffer(i, buffer->bufsize());
}
return detail;
}
buffer_sptr
flat_flowgraph::allocate_buffer(basic_block_sptr block, int port)
{
block_sptr grblock = cast_to_block_sptr(block);
if(!grblock)
throw std::runtime_error("allocate_buffer found non-gr::block");
int item_size = block->output_signature()->sizeof_stream_item(port);
// *2 because we're now only filling them 1/2 way in order to
// increase the available parallelism when using the TPB scheduler.
// (We're double buffering, where we used to single buffer)
int nitems = s_fixed_buffer_size * 2 / item_size;
// Make sure there are at least twice the output_multiple no. of items
if(nitems < 2*grblock->output_multiple()) // Note: this means output_multiple()
nitems = 2*grblock->output_multiple(); // can't be changed by block dynamically
// If any downstream blocks are decimators and/or have a large output_multiple,
// ensure we have a buffer at least twice their decimation factor*output_multiple
basic_block_vector_t blocks = calc_downstream_blocks(block, port);
// limit buffer size if indicated
if(grblock->max_output_buffer(port) > 0) {
//std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n";
nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port));
nitems -= nitems%grblock->output_multiple();
if(nitems < 1)
throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!");
}
else if(grblock->min_output_buffer(port) > 0) {
nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port));
nitems -= nitems%grblock->output_multiple();
if(nitems < 1)
throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!");
}
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
block_sptr dgrblock = cast_to_block_sptr(*p);
if(!dgrblock)
throw std::runtime_error("allocate_buffer found non-gr::block");
double decimation = (1.0/dgrblock->relative_rate());
int multiple = dgrblock->output_multiple();
int history = dgrblock->history();
nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history)));
}
// std::cout << "make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n";
// We're going to let this fail once and retry. If that fails,
// throw and exit.
buffer_sptr b;
try {
b = make_buffer(nitems, item_size, grblock);
}
catch(std::bad_alloc&) {
b = make_buffer(nitems, item_size, grblock);
}
return b;
}
void
flat_flowgraph::connect_block_inputs(basic_block_sptr block)
{
block_sptr grblock = cast_to_block_sptr(block);
if (!grblock)
throw std::runtime_error("connect_block_inputs found non-gr::block");
// Get its detail and edges that feed into it
block_detail_sptr detail = grblock->detail();
edge_vector_t in_edges = calc_upstream_edges(block);
// For each edge that feeds into it
for(edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
// Set the buffer reader on the destination port to the output
// buffer on the source port
int dst_port = e->dst().port();
int src_port = e->src().port();
basic_block_sptr src_block = e->src().block();
block_sptr src_grblock = cast_to_block_sptr(src_block);
if(!src_grblock)
throw std::runtime_error("connect_block_inputs found non-gr::block");
buffer_sptr src_buffer = src_grblock->detail()->output(src_port);
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "Setting input " << dst_port << " from edge " << (*e) << std::endl;
detail->set_input(dst_port, buffer_add_reader(src_buffer, grblock->history()-1, grblock));
}
}
void
flat_flowgraph::merge_connections(flat_flowgraph_sptr old_ffg)
{
// Allocate block details if needed. Only new blocks that aren't pruned out
// by flattening will need one; existing blocks still in the new flowgraph will
// already have one.
for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
block_sptr block = cast_to_block_sptr(*p);
if(!block->detail()) {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "merge: allocating new detail for block " << (*p) << std::endl;
block->set_detail(allocate_block_detail(block));
}
else
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "merge: reusing original detail for block " << (*p) << std::endl;
}
// Calculate the old edges that will be going away, and clear the
// buffer readers on the RHS.
for(edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "merge: testing old edge " << (*old_edge) << "...";
edge_viter_t new_edge;
for(new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++)
if(new_edge->src() == old_edge->src() &&
new_edge->dst() == old_edge->dst())
break;
if(new_edge == d_edges.end()) { // not found in new edge list
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "not in new edge list" << std::endl;
// zero the buffer reader on RHS of old edge
block_sptr block(cast_to_block_sptr(old_edge->dst().block()));
int port = old_edge->dst().port();
block->detail()->set_input(port, buffer_reader_sptr());
}
else {
if (FLAT_FLOWGRAPH_DEBUG)
std::cout << "found in new edge list" << std::endl;
}
}
// Now connect inputs to outputs, reusing old buffer readers if they exist
for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
block_sptr block = cast_to_block_sptr(*p);
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "merge: merging " << (*p) << "...";
if(old_ffg->has_block_p(*p)) {
// Block exists in old flow graph
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "used in old flow graph" << std::endl;
block_detail_sptr detail = block->detail();
// Iterate through the inputs and see what needs to be done
int ninputs = calc_used_ports(block, true).size(); // Might be different now
for(int i = 0; i < ninputs; i++) {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "Checking input " << block << ":" << i << "...";
edge edge = calc_upstream_edge(*p, i);
// Fish out old buffer reader and see if it matches correct buffer from edge list
block_sptr src_block = cast_to_block_sptr(edge.src().block());
block_detail_sptr src_detail = src_block->detail();
buffer_sptr src_buffer = src_detail->output(edge.src().port());
buffer_reader_sptr old_reader;
if(i < detail->ninputs()) // Don't exceed what the original detail has
old_reader = detail->input(i);
// If there's a match, use it
if(old_reader && (src_buffer == old_reader->buffer())) {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "matched, reusing" << std::endl;
}
else {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "needs a new reader" << std::endl;
// Create new buffer reader and assign
detail->set_input(i, buffer_add_reader(src_buffer, block->history()-1, block));
}
}
}
else {
// Block is new, it just needs buffer readers at this point
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "new block" << std::endl;
connect_block_inputs(block);
// Make sure all buffers are aligned
setup_buffer_alignment(block);
}
// Now deal with the fact that the block details might have
// changed numbers of inputs and outputs vs. in the old
// flowgraph.
}
}
void
flat_flowgraph::setup_buffer_alignment(block_sptr block)
{
const int alignment = 4; //volk_get_alignment(); // FIXME: check alignment
for(int i = 0; i < block->detail()->ninputs(); i++) {
void *r = (void*)block->detail()->input(i)->read_pointer();
unsigned long int ri = (unsigned long int)r % alignment;
//std::cerr << "reader: " << r << " alignment: " << ri << std::endl;
if(ri != 0) {
size_t itemsize = block->detail()->input(i)->get_sizeof_item();
block->detail()->input(i)->update_read_pointer(alignment-ri/itemsize);
}
block->set_unaligned(0);
block->set_is_unaligned(false);
}
for(int i = 0; i < block->detail()->noutputs(); i++) {
void *w = (void*)block->detail()->output(i)->write_pointer();
unsigned long int wi = (unsigned long int)w % alignment;
//std::cerr << "writer: " << w << " alignment: " << wi << std::endl;
if(wi != 0) {
size_t itemsize = block->detail()->output(i)->get_sizeof_item();
block->detail()->output(i)->update_write_pointer(alignment-wi/itemsize);
}
block->set_unaligned(0);
block->set_is_unaligned(false);
}
}
std::string
flat_flowgraph::edge_list()
{
std::stringstream s;
for(edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++)
s << (*e) << std::endl;
return s.str();
}
void flat_flowgraph::dump()
{
for(edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++)
std::cout << " edge: " << (*e) << std::endl;
for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
std::cout << " block: " << (*p) << std::endl;
block_detail_sptr detail = cast_to_block_sptr(*p)->detail();
std::cout << " detail @" << detail << ":" << std::endl;
int ni = detail->ninputs();
int no = detail->noutputs();
for(int i = 0; i < no; i++) {
buffer_sptr buffer = detail->output(i);
std::cout << " output " << i << ": " << buffer << std::endl;
}
for(int i = 0; i < ni; i++) {
buffer_reader_sptr reader = detail->input(i);
std::cout << " reader " << i << ": " << reader
<< " reading from buffer=" << reader->buffer() << std::endl;
}
}
}
block_vector_t
flat_flowgraph::make_block_vector(basic_block_vector_t &blocks)
{
block_vector_t result;
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
result.push_back(cast_to_block_sptr(*p));
}
return result;
}
void
flat_flowgraph::enable_pc_rpc()
{
#ifdef GR_PERFORMANCE_COUNTERS
if(prefs::singleton()->get_bool("PerfCounters", "on", false)) {
basic_block_viter_t p;
for(p = d_blocks.begin(); p != d_blocks.end(); p++) {
block_sptr block = cast_to_block_sptr(*p);
if(!block->is_pc_rpc_set())
block->setup_pc_rpc();
}
}
#endif /* GR_PERFORMANCE_COUNTERS */
}
} /* namespace gr */

View File

@ -0,0 +1,90 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2007,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H
#define INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H
#include <gnuradio/api.h>
#include <gnuradio/flowgraph.h>
#include <gnuradio/block.h>
namespace gr {
// Create a shared pointer to a heap allocated gr::flat_flowgraph
// (types defined in gr_runtime_types.h)
GR_RUNTIME_API flat_flowgraph_sptr make_flat_flowgraph();
/*!
*\brief Class specializing gr_flat_flowgraph that has all nodes
* as blocks, with no hierarchy
* \ingroup internal
*/
class GR_RUNTIME_API flat_flowgraph : public flowgraph
{
public:
friend GR_RUNTIME_API flat_flowgraph_sptr make_flat_flowgraph();
// Destruct an arbitrary gr::flat_flowgraph
~flat_flowgraph();
// Wire list of gr::block together in new flat_flowgraph
void setup_connections();
// Merge applicable connections from existing flat flowgraph
void merge_connections(flat_flowgraph_sptr sfg);
// Return a string list of edges
std::string edge_list();
void dump();
/*!
* Make a vector of gr::block from a vector of gr::basic_block
*/
static block_vector_t make_block_vector(basic_block_vector_t &blocks);
/*!
* Enables export of perf. counters to ControlPort on all blocks in
* the flowgraph.
*/
void enable_pc_rpc();
private:
flat_flowgraph();
block_detail_sptr allocate_block_detail(basic_block_sptr block);
buffer_sptr allocate_buffer(basic_block_sptr block, int port);
void connect_block_inputs(basic_block_sptr block);
/* When reusing a flowgraph's blocks, this call makes sure all of
* the buffer's are aligned at the machine's alignment boundary
* and tells the blocks that they are aligned.
*
* Called from both setup_connections and merge_connections for
* start and restarts.
*/
void setup_buffer_alignment(block_sptr block);
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H */

475
lib/runtime/flowgraph.cc Normal file
View File

@ -0,0 +1,475 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/flowgraph.h>
#include <stdexcept>
#include <sstream>
#include <iterator>
namespace gr {
#define FLOWGRAPH_DEBUG 0
edge::~edge()
{
}
flowgraph_sptr make_flowgraph()
{
return flowgraph_sptr(new flowgraph());
}
flowgraph::flowgraph()
{
}
flowgraph::~flowgraph()
{
}
template<class T>
static
std::vector<T>
unique_vector(std::vector<T> v)
{
std::vector<T> result;
std::insert_iterator<std::vector<T> > inserter(result, result.begin());
sort(v.begin(), v.end());
unique_copy(v.begin(), v.end(), inserter);
return result;
}
void
flowgraph::connect(const endpoint &src, const endpoint &dst)
{
check_valid_port(src.block()->output_signature(), src.port());
check_valid_port(dst.block()->input_signature(), dst.port());
check_dst_not_used(dst);
check_type_match(src, dst);
// All ist klar, Herr Kommisar
d_edges.push_back(edge(src,dst));
}
void
flowgraph::disconnect(const endpoint &src, const endpoint &dst)
{
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
if(src == p->src() && dst == p->dst()) {
d_edges.erase(p);
return;
}
}
std::stringstream msg;
msg << "cannot disconnect edge " << edge(src, dst) << ", not found";
throw std::invalid_argument(msg.str());
}
void
flowgraph::validate()
{
d_blocks = calc_used_blocks();
for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
std::vector<int> used_ports;
int ninputs, noutputs;
if(FLOWGRAPH_DEBUG)
std::cout << "Validating block: " << (*p) << std::endl;
used_ports = calc_used_ports(*p, true); // inputs
ninputs = used_ports.size();
check_contiguity(*p, used_ports, true); // inputs
used_ports = calc_used_ports(*p, false); // outputs
noutputs = used_ports.size();
check_contiguity(*p, used_ports, false); // outputs
if(!((*p)->check_topology(ninputs, noutputs))) {
std::stringstream msg;
msg << "check topology failed on " << (*p)
<< " using ninputs=" << ninputs
<< ", noutputs=" << noutputs;
throw std::runtime_error(msg.str());
}
}
}
void
flowgraph::clear()
{
// Boost shared pointers will deallocate as needed
d_blocks.clear();
d_edges.clear();
}
void
flowgraph::check_valid_port(gr::io_signature::sptr sig, int port)
{
std::stringstream msg;
if(port < 0) {
msg << "negative port number " << port << " is invalid";
throw std::invalid_argument(msg.str());
}
int max = sig->max_streams();
if(max != io_signature::IO_INFINITE && port >= max) {
msg << "port number " << port << " exceeds max of ";
if(max == 0)
msg << "(none)";
else
msg << max-1;
throw std::invalid_argument(msg.str());
}
}
void
flowgraph::check_dst_not_used(const endpoint &dst)
{
// A destination is in use if it is already on the edge list
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
if(p->dst() == dst) {
std::stringstream msg;
msg << "destination already in use by edge " << (*p);
throw std::invalid_argument(msg.str());
}
}
void
flowgraph::check_type_match(const endpoint &src, const endpoint &dst)
{
int src_size = src.block()->output_signature()->sizeof_stream_item(src.port());
int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port());
if(src_size != dst_size) {
std::stringstream msg;
msg << "itemsize mismatch: " << src << " using " << src_size
<< ", " << dst << " using " << dst_size;
throw std::invalid_argument(msg.str());
}
}
basic_block_vector_t
flowgraph::calc_used_blocks()
{
basic_block_vector_t tmp;
// Collect all blocks in the edge list
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
tmp.push_back(p->src().block());
tmp.push_back(p->dst().block());
}
return unique_vector<basic_block_sptr>(tmp);
}
std::vector<int>
flowgraph::calc_used_ports(basic_block_sptr block, bool check_inputs)
{
std::vector<int> tmp;
// Collect all seen ports
edge_vector_t edges = calc_connections(block, check_inputs);
for(edge_viter_t p = edges.begin(); p != edges.end(); p++) {
if(check_inputs == true)
tmp.push_back(p->dst().port());
else
tmp.push_back(p->src().port());
}
return unique_vector<int>(tmp);
}
edge_vector_t
flowgraph::calc_connections(basic_block_sptr block, bool check_inputs)
{
edge_vector_t result;
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
if(check_inputs) {
if(p->dst().block() == block)
result.push_back(*p);
}
else {
if(p->src().block() == block)
result.push_back(*p);
}
}
return result; // assumes no duplicates
}
void
flowgraph::check_contiguity(basic_block_sptr block,
const std::vector<int> &used_ports,
bool check_inputs)
{
std::stringstream msg;
gr::io_signature::sptr sig =
check_inputs ? block->input_signature() : block->output_signature();
int nports = used_ports.size();
int min_ports = sig->min_streams();
int max_ports = sig->max_streams();
if(nports == 0 && min_ports == 0)
return;
if(nports < min_ports) {
msg << block << ": insufficient connected "
<< (check_inputs ? "input ports " : "output ports ")
<< "(" << min_ports << " needed, " << nports << " connected)";
throw std::runtime_error(msg.str());
}
if(nports > max_ports && max_ports != io_signature::IO_INFINITE) {
msg << block << ": too many connected "
<< (check_inputs ? "input ports " : "output ports ")
<< "(" << max_ports << " allowed, " << nports << " connected)";
throw std::runtime_error(msg.str());
}
if(used_ports[nports-1]+1 != nports) {
for(int i = 0; i < nports; i++) {
if(used_ports[i] != i) {
msg << block << ": missing connection "
<< (check_inputs ? "to input port " : "from output port ")
<< i;
throw std::runtime_error(msg.str());
}
}
}
}
basic_block_vector_t
flowgraph::calc_downstream_blocks(basic_block_sptr block, int port)
{
basic_block_vector_t tmp;
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
if(p->src() == endpoint(block, port))
tmp.push_back(p->dst().block());
return unique_vector<basic_block_sptr>(tmp);
}
basic_block_vector_t
flowgraph::calc_downstream_blocks(basic_block_sptr block)
{
basic_block_vector_t tmp;
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
if(p->src().block() == block)
tmp.push_back(p->dst().block());
return unique_vector<basic_block_sptr>(tmp);
}
edge_vector_t
flowgraph::calc_upstream_edges(basic_block_sptr block)
{
edge_vector_t result;
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
if(p->dst().block() == block)
result.push_back(*p);
return result; // Assume no duplicates
}
bool
flowgraph::has_block_p(basic_block_sptr block)
{
basic_block_viter_t result;
result = std::find(d_blocks.begin(), d_blocks.end(), block);
return (result != d_blocks.end());
}
edge
flowgraph::calc_upstream_edge(basic_block_sptr block, int port)
{
edge result;
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
if(p->dst() == endpoint(block, port)) {
result = (*p);
break;
}
}
return result;
}
std::vector<basic_block_vector_t>
flowgraph::partition()
{
std::vector<basic_block_vector_t> result;
basic_block_vector_t blocks = calc_used_blocks();
basic_block_vector_t graph;
while(blocks.size() > 0) {
graph = calc_reachable_blocks(blocks[0], blocks);
assert(graph.size());
result.push_back(topological_sort(graph));
for(basic_block_viter_t p = graph.begin(); p != graph.end(); p++)
blocks.erase(find(blocks.begin(), blocks.end(), *p));
}
return result;
}
basic_block_vector_t
flowgraph::calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks)
{
basic_block_vector_t result;
// Mark all blocks as unvisited
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
(*p)->set_color(basic_block::WHITE);
// Recursively mark all reachable blocks
reachable_dfs_visit(block, blocks);
// Collect all the blocks that have been visited
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
if((*p)->color() == basic_block::BLACK)
result.push_back(*p);
return result;
}
// Recursively mark all reachable blocks from given block and block list
void
flowgraph::reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks)
{
// Mark the current one as visited
block->set_color(basic_block::BLACK);
// Recurse into adjacent vertices
basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
for(basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
if((*p)->color() == basic_block::WHITE)
reachable_dfs_visit(*p, blocks);
}
// Return a list of block adjacent to a given block along any edge
basic_block_vector_t
flowgraph::calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks)
{
basic_block_vector_t tmp;
// Find any blocks that are inputs or outputs
for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
if(p->src().block() == block)
tmp.push_back(p->dst().block());
if(p->dst().block() == block)
tmp.push_back(p->src().block());
}
return unique_vector<basic_block_sptr>(tmp);
}
basic_block_vector_t
flowgraph::topological_sort(basic_block_vector_t &blocks)
{
basic_block_vector_t tmp;
basic_block_vector_t result;
tmp = sort_sources_first(blocks);
// Start 'em all white
for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
(*p)->set_color(basic_block::WHITE);
for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
if((*p)->color() == basic_block::WHITE)
topological_dfs_visit(*p, result);
}
reverse(result.begin(), result.end());
return result;
}
basic_block_vector_t
flowgraph::sort_sources_first(basic_block_vector_t &blocks)
{
basic_block_vector_t sources, nonsources, result;
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
if(source_p(*p))
sources.push_back(*p);
else
nonsources.push_back(*p);
}
for(basic_block_viter_t p = sources.begin(); p != sources.end(); p++)
result.push_back(*p);
for(basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
result.push_back(*p);
return result;
}
bool
flowgraph::source_p(basic_block_sptr block)
{
return (calc_upstream_edges(block).size() == 0);
}
void
flowgraph::topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output)
{
block->set_color(basic_block::GREY);
basic_block_vector_t blocks(calc_downstream_blocks(block));
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
switch((*p)->color()) {
case basic_block::WHITE:
topological_dfs_visit(*p, output);
break;
case basic_block::GREY:
throw std::runtime_error("flow graph has loops!");
case basic_block::BLACK:
continue;
default:
throw std::runtime_error("invalid color on block!");
}
}
block->set_color(basic_block::BLACK);
output.push_back(block);
}
} /* namespace gr */

142
lib/runtime/hier_block2.cc Normal file
View File

@ -0,0 +1,142 @@
/* -*- c++ -*- */
/*
* Copyright 2006-2008,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/hier_block2.h>
#include <gnuradio/io_signature.h>
#include "hier_block2_detail.h"
#include <iostream>
namespace gr {
#define GR_HIER_BLOCK2_DEBUG 0
hier_block2_sptr
make_hier_block2(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature)
{
return gnuradio::get_initial_sptr
(new hier_block2(name, input_signature, output_signature));
}
hier_block2::hier_block2(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature)
: basic_block(name, input_signature, output_signature),
d_detail(new hier_block2_detail(this))
{
// This bit of magic ensures that self() works in the constructors of derived classes.
gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this);
}
hier_block2::~hier_block2()
{
delete d_detail;
}
hier_block2::opaque_self
hier_block2::self()
{
return shared_from_this();
}
hier_block2_sptr
hier_block2::to_hier_block2()
{
return cast_to_hier_block2_sptr(shared_from_this());
}
void
hier_block2::connect(basic_block_sptr block)
{
d_detail->connect(block);
}
void
hier_block2::connect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port)
{
d_detail->connect(src, src_port, dst, dst_port);
}
void
hier_block2::disconnect(basic_block_sptr block)
{
d_detail->disconnect(block);
}
void
hier_block2::disconnect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port)
{
d_detail->disconnect(src, src_port, dst, dst_port);
}
void
hier_block2::disconnect_all()
{
d_detail->disconnect_all();
}
void
hier_block2::lock()
{
d_detail->lock();
}
void
hier_block2::unlock()
{
d_detail->unlock();
}
flat_flowgraph_sptr
hier_block2::flatten() const
{
flat_flowgraph_sptr new_ffg = make_flat_flowgraph();
d_detail->flatten_aux(new_ffg);
return new_ffg;
}
void
hier_block2::set_processor_affinity(const std::vector<int> &mask)
{
d_detail->set_processor_affinity(mask);
}
void
hier_block2::unset_processor_affinity()
{
d_detail->unset_processor_affinity();
}
std::vector<int>
hier_block2::processor_affinity()
{
return d_detail->processor_affinity();
}
} /* namespace gr */

View File

@ -0,0 +1,566 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2007,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hier_block2_detail.h"
#include <gnuradio/io_signature.h>
#include <gnuradio/prefs.h>
#include <stdexcept>
#include <sstream>
#include <boost/format.hpp>
namespace gr {
#define HIER_BLOCK2_DETAIL_DEBUG 0
hier_block2_detail::hier_block2_detail(hier_block2 *owner)
: d_owner(owner),
d_parent_detail(0),
d_fg(make_flowgraph())
{
int min_inputs = owner->input_signature()->min_streams();
int max_inputs = owner->input_signature()->max_streams();
int min_outputs = owner->output_signature()->min_streams();
int max_outputs = owner->output_signature()->max_streams();
if(max_inputs == io_signature::IO_INFINITE ||
max_outputs == io_signature::IO_INFINITE ||
(min_inputs != max_inputs) ||(min_outputs != max_outputs) ) {
std::stringstream msg;
msg << "Hierarchical blocks do not yet support arbitrary or"
<< " variable numbers of inputs or outputs (" << d_owner->name() << ")";
throw std::runtime_error(msg.str());
}
d_inputs = std::vector<endpoint_vector_t>(max_inputs);
d_outputs = endpoint_vector_t(max_outputs);
}
hier_block2_detail::~hier_block2_detail()
{
d_owner = 0; // Don't use delete, we didn't allocate
}
void
hier_block2_detail::connect(basic_block_sptr block)
{
std::stringstream msg;
// Check if duplicate
if(std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) {
msg << "Block " << block << " already connected.";
throw std::invalid_argument(msg.str());
}
// Check if has inputs or outputs
if(block->input_signature()->max_streams() != 0 ||
block->output_signature()->max_streams() != 0) {
msg << "Block " << block << " must not have any input or output ports";
throw std::invalid_argument(msg.str());
}
hier_block2_sptr hblock(cast_to_hier_block2_sptr(block));
if(hblock && hblock.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "connect: block is hierarchical, setting parent to " << this << std::endl;
hblock->d_detail->d_parent_detail = this;
}
d_blocks.push_back(block);
}
void
hier_block2_detail::connect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port)
{
std::stringstream msg;
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "connecting: " << endpoint(src, src_port)
<< " -> " << endpoint(dst, dst_port) << std::endl;
if(src.get() == dst.get())
throw std::invalid_argument("connect: src and destination blocks cannot be the same");
hier_block2_sptr src_block(cast_to_hier_block2_sptr(src));
hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst));
if(src_block && src.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl;
src_block->d_detail->d_parent_detail = this;
}
if(dst_block && dst.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl;
dst_block->d_detail->d_parent_detail = this;
}
// Connections to block inputs or outputs
int max_port;
if(src.get() == d_owner) {
max_port = src->input_signature()->max_streams();
if((max_port != -1 && (src_port >= max_port)) || src_port < 0) {
msg << "source port " << src_port << " out of range for " << src;
throw std::invalid_argument(msg.str());
}
return connect_input(src_port, dst_port, dst);
}
if(dst.get() == d_owner) {
max_port = dst->output_signature()->max_streams();
if((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) {
msg << "destination port " << dst_port << " out of range for " << dst;
throw std::invalid_argument(msg.str());
}
return connect_output(dst_port, src_port, src);
}
// Internal connections
d_fg->connect(src, src_port, dst, dst_port);
// TODO: connects to NC
}
void
hier_block2_detail::disconnect(basic_block_sptr block)
{
// Check on singleton list
for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
if(*p == block) {
d_blocks.erase(p);
hier_block2_sptr hblock(cast_to_hier_block2_sptr(block));
if(block && block.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "disconnect: block is hierarchical, clearing parent" << std::endl;
hblock->d_detail->d_parent_detail = 0;
}
return;
}
}
// Otherwise find all edges containing block
edge_vector_t edges, tmp = d_fg->edges();
edge_vector_t::iterator p;
for(p = tmp.begin(); p != tmp.end(); p++) {
if((*p).src().block() == block || (*p).dst().block() == block) {
edges.push_back(*p);
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "disconnect: block found in edge " << (*p) << std::endl;
}
}
if(edges.size() == 0) {
std::stringstream msg;
msg << "cannot disconnect block " << block << ", not found";
throw std::invalid_argument(msg.str());
}
for(p = edges.begin(); p != edges.end(); p++) {
disconnect((*p).src().block(), (*p).src().port(),
(*p).dst().block(), (*p).dst().port());
}
}
void
hier_block2_detail::disconnect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port)
{
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "disconnecting: " << endpoint(src, src_port)
<< " -> " << endpoint(dst, dst_port) << std::endl;
if(src.get() == dst.get())
throw std::invalid_argument("disconnect: source and destination blocks cannot be the same");
hier_block2_sptr src_block(cast_to_hier_block2_sptr(src));
hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst));
if(src_block && src.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "disconnect: src is hierarchical, clearing parent" << std::endl;
src_block->d_detail->d_parent_detail = 0;
}
if(dst_block && dst.get() != d_owner) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "disconnect: dst is hierarchical, clearing parent" << std::endl;
dst_block->d_detail->d_parent_detail = 0;
}
if(src.get() == d_owner)
return disconnect_input(src_port, dst_port, dst);
if(dst.get() == d_owner)
return disconnect_output(dst_port, src_port, src);
// Internal connections
d_fg->disconnect(src, src_port, dst, dst_port);
}
void
hier_block2_detail::connect_input(int my_port, int port,
basic_block_sptr block)
{
std::stringstream msg;
if(my_port < 0 || my_port >= (signed)d_inputs.size()) {
msg << "input port " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
}
endpoint_vector_t &endps = d_inputs[my_port];
endpoint endp(block, port);
endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp);
if(p != endps.end()) {
msg << "external input port " << my_port << " already wired to " << endp;
throw std::invalid_argument(msg.str());
}
endps.push_back(endp);
}
void
hier_block2_detail::connect_output(int my_port, int port,
basic_block_sptr block)
{
std::stringstream msg;
if(my_port < 0 || my_port >= (signed)d_outputs.size()) {
msg << "output port " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
}
if(d_outputs[my_port].block()) {
msg << "external output port " << my_port << " already connected from "
<< d_outputs[my_port];
throw std::invalid_argument(msg.str());
}
d_outputs[my_port] = endpoint(block, port);
}
void
hier_block2_detail::disconnect_input(int my_port, int port,
basic_block_sptr block)
{
std::stringstream msg;
if(my_port < 0 || my_port >= (signed)d_inputs.size()) {
msg << "input port number " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
}
endpoint_vector_t &endps = d_inputs[my_port];
endpoint endp(block, port);
endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp);
if(p == endps.end()) {
msg << "external input port " << my_port << " not connected to " << endp;
throw std::invalid_argument(msg.str());
}
endps.erase(p);
}
void
hier_block2_detail::disconnect_output(int my_port, int port,
basic_block_sptr block)
{
std::stringstream msg;
if(my_port < 0 || my_port >= (signed)d_outputs.size()) {
msg << "output port number " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
}
if(d_outputs[my_port].block() != block) {
msg << "block " << block << " not assigned to output "
<< my_port << ", can't disconnect";
throw std::invalid_argument(msg.str());
}
d_outputs[my_port] = endpoint();
}
endpoint_vector_t
hier_block2_detail::resolve_port(int port, bool is_input)
{
std::stringstream msg;
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "Resolving port " << port << " as an "
<< (is_input ? "input" : "output")
<< " of " << d_owner->name() << std::endl;
endpoint_vector_t result;
if(is_input) {
if(port < 0 || port >= (signed)d_inputs.size()) {
msg << "resolve_port: hierarchical block '" << d_owner->name()
<< "': input " << port << " is out of range";
throw std::runtime_error(msg.str());
}
if(d_inputs[port].empty()) {
msg << "resolve_port: hierarchical block '" << d_owner->name()
<< "': input " << port << " is not connected internally";
throw std::runtime_error(msg.str());
}
endpoint_vector_t &endps = d_inputs[port];
endpoint_viter_t p;
for(p = endps.begin(); p != endps.end(); p++) {
endpoint_vector_t tmp = resolve_endpoint(*p, true);
std::copy(tmp.begin(), tmp.end(), back_inserter(result));
}
}
else {
if(port < 0 || port >= (signed)d_outputs.size()) {
msg << "resolve_port: hierarchical block '" << d_owner->name()
<< "': output " << port << " is out of range";
throw std::runtime_error(msg.str());
}
if(d_outputs[port] == endpoint()) {
msg << "resolve_port: hierarchical block '" << d_owner->name()
<< "': output " << port << " is not connected internally";
throw std::runtime_error(msg.str());
}
result = resolve_endpoint(d_outputs[port], false);
}
if(result.empty()) {
msg << "resolve_port: hierarchical block '" << d_owner->name()
<< "': unable to resolve "
<< (is_input ? "input port " : "output port ")
<< port;
throw std::runtime_error(msg.str());
}
return result;
}
void
hier_block2_detail::disconnect_all()
{
d_fg->clear();
d_blocks.clear();
d_inputs.clear();
d_outputs.clear();
}
endpoint_vector_t
hier_block2_detail::resolve_endpoint(const endpoint &endp, bool is_input) const
{
std::stringstream msg;
endpoint_vector_t result;
// Check if endpoint is a leaf node
if(cast_to_block_sptr(endp.block())) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "Block " << endp.block() << " is a leaf node, returning." << std::endl;
result.push_back(endp);
return result;
}
// Check if endpoint is a hierarchical block
hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(endp.block()));
if(hier_block2) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "Resolving endpoint " << endp << " as an "
<< (is_input ? "input" : "output")
<< ", recursing" << std::endl;
return hier_block2->d_detail->resolve_port(endp.port(), is_input);
}
msg << "unable to resolve" << (is_input ? " input " : " output ")
<< "endpoint " << endp;
throw std::runtime_error(msg.str());
}
void
hier_block2_detail::flatten_aux(flat_flowgraph_sptr sfg) const
{
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << " ** Flattening " << d_owner->name() << std::endl;
// Add my edges to the flow graph, resolving references to actual endpoints
edge_vector_t edges = d_fg->edges();
edge_viter_t p;
// Only run setup_rpc if ControlPort config param is enabled.
bool ctrlport_on = prefs::singleton()->get_bool("ControlPort", "on", false);
// For every block (gr::block and gr::hier_block2), set up the RPC
// interface.
for(p = edges.begin(); p != edges.end(); p++) {
basic_block_sptr b;
b = p->src().block();
if(ctrlport_on) {
if(!b->is_rpc_set()) {
b->setup_rpc();
b->rpc_set();
}
}
b = p->dst().block();
if(ctrlport_on) {
if(!b->is_rpc_set()) {
b->setup_rpc();
b->rpc_set();
}
}
}
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "Flattening stream connections: " << std::endl;
for(p = edges.begin(); p != edges.end(); p++) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "Flattening edge " << (*p) << std::endl;
endpoint_vector_t src_endps = resolve_endpoint(p->src(), false);
endpoint_vector_t dst_endps = resolve_endpoint(p->dst(), true);
endpoint_viter_t s, d;
for(s = src_endps.begin(); s != src_endps.end(); s++) {
for(d = dst_endps.begin(); d != dst_endps.end(); d++) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << (*s) << "->" << (*d) << std::endl;
sfg->connect(*s, *d);
}
}
}
// Construct unique list of blocks used either in edges, inputs,
// outputs, or by themselves. I still hate STL.
basic_block_vector_t blocks; // unique list of used blocks
basic_block_vector_t tmp = d_fg->calc_used_blocks();
// First add the list of singleton blocks
std::vector<basic_block_sptr>::const_iterator b; // Because flatten_aux is const
for(b = d_blocks.begin(); b != d_blocks.end(); b++)
tmp.push_back(*b);
// Now add the list of connected input blocks
std::stringstream msg;
for(unsigned int i = 0; i < d_inputs.size(); i++) {
if(d_inputs[i].size() == 0) {
msg << "In hierarchical block " << d_owner->name() << ", input " << i
<< " is not connected internally";
throw std::runtime_error(msg.str());
}
for(unsigned int j = 0; j < d_inputs[i].size(); j++)
tmp.push_back(d_inputs[i][j].block());
}
for(unsigned int i = 0; i < d_outputs.size(); i++) {
basic_block_sptr blk = d_outputs[i].block();
if(!blk) {
msg << "In hierarchical block " << d_owner->name() << ", output " << i
<< " is not connected internally";
throw std::runtime_error(msg.str());
}
tmp.push_back(blk);
}
sort(tmp.begin(), tmp.end());
std::insert_iterator<basic_block_vector_t> inserter(blocks, blocks.begin());
unique_copy(tmp.begin(), tmp.end(), inserter);
// Recurse hierarchical children
for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p));
if(hier_block2 && (hier_block2.get() != d_owner)) {
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "flatten_aux: recursing into hierarchical block "
<< hier_block2 << std::endl;
hier_block2->d_detail->flatten_aux(sfg);
}
}
}
void
hier_block2_detail::lock()
{
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "lock: entered in " << this << std::endl;
if(d_parent_detail)
d_parent_detail->lock();
else
d_owner->lock();
}
void
hier_block2_detail::unlock()
{
if(HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "unlock: entered in " << this << std::endl;
if(d_parent_detail)
d_parent_detail->unlock();
else
d_owner->unlock();
}
void
hier_block2_detail::set_processor_affinity(const std::vector<int> &mask)
{
basic_block_vector_t tmp = d_fg->calc_used_blocks();
for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
(*p)->set_processor_affinity(mask);
}
}
void
hier_block2_detail::unset_processor_affinity()
{
basic_block_vector_t tmp = d_fg->calc_used_blocks();
for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
(*p)->unset_processor_affinity();
}
}
std::vector<int>
hier_block2_detail::processor_affinity()
{
basic_block_vector_t tmp = d_fg->calc_used_blocks();
return tmp[0]->processor_affinity();
}
} /* namespace gr */

View File

@ -0,0 +1,77 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2007,2009,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H
#define INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H
#include <gnuradio/api.h>
#include <gnuradio/hier_block2.h>
#include <flat_flowgraph.h>
#include <boost/utility.hpp>
namespace gr {
/*!
* \ingroup internal
*/
class GR_RUNTIME_API hier_block2_detail : boost::noncopyable
{
public:
hier_block2_detail(hier_block2 *owner);
~hier_block2_detail();
void connect(basic_block_sptr block);
void connect(basic_block_sptr src, int src_port,
basic_block_sptr dst, int dst_port);
void disconnect(basic_block_sptr block);
void disconnect(basic_block_sptr, int src_port,
basic_block_sptr, int dst_port);
void disconnect_all();
void lock();
void unlock();
void flatten_aux(flat_flowgraph_sptr sfg) const;
void set_processor_affinity(const std::vector<int> &mask);
void unset_processor_affinity();
std::vector<int> processor_affinity();
private:
// Private implementation data
hier_block2 *d_owner;
hier_block2_detail *d_parent_detail;
flowgraph_sptr d_fg;
std::vector<endpoint_vector_t> d_inputs; // Multiple internal endpoints per external input
endpoint_vector_t d_outputs; // Single internal endpoint per external output
basic_block_vector_t d_blocks;
void connect_input(int my_port, int port, basic_block_sptr block);
void connect_output(int my_port, int port, basic_block_sptr block);
void disconnect_input(int my_port, int port, basic_block_sptr block);
void disconnect_output(int my_port, int port, basic_block_sptr block);
endpoint_vector_t resolve_port(int port, bool is_input);
endpoint_vector_t resolve_endpoint(const endpoint &endp, bool is_input) const;
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H */

View File

@ -0,0 +1,8 @@
#include <gnuradio/high_res_timer.h>
#ifdef GNURADIO_HRT_USE_CLOCK_GETTIME
clockid_t gr::high_res_timer_source = CLOCK_THREAD_CPUTIME_ID;
#endif

117
lib/runtime/io_signature.cc Normal file
View File

@ -0,0 +1,117 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2007,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnuradio/io_signature.h>
#include <stdexcept>
#include <iostream>
namespace gr {
gr::io_signature::sptr
io_signature::makev(int min_streams, int max_streams,
const std::vector<int> &sizeof_stream_items)
{
return gr::io_signature::sptr
(new io_signature(min_streams, max_streams,
sizeof_stream_items));
}
gr::io_signature::sptr
io_signature::make(int min_streams, int max_streams,
int sizeof_stream_item)
{
std::vector<int> sizeof_items(1);
sizeof_items[0] = sizeof_stream_item;
return io_signature::makev(min_streams, max_streams, sizeof_items);
}
gr::io_signature::sptr
io_signature::make2(int min_streams, int max_streams,
int sizeof_stream_item1,
int sizeof_stream_item2)
{
std::vector<int> sizeof_items(2);
sizeof_items[0] = sizeof_stream_item1;
sizeof_items[1] = sizeof_stream_item2;
return io_signature::makev(min_streams, max_streams, sizeof_items);
}
gr::io_signature::sptr
io_signature::make3(int min_streams, int max_streams,
int sizeof_stream_item1,
int sizeof_stream_item2,
int sizeof_stream_item3)
{
std::vector<int> sizeof_items(3);
sizeof_items[0] = sizeof_stream_item1;
sizeof_items[1] = sizeof_stream_item2;
sizeof_items[2] = sizeof_stream_item3;
return io_signature::makev(min_streams, max_streams, sizeof_items);
}
// ------------------------------------------------------------------------
io_signature::io_signature(int min_streams, int max_streams,
const std::vector<int> &sizeof_stream_items)
{
if(min_streams < 0
|| (max_streams != IO_INFINITE && max_streams < min_streams))
throw std::invalid_argument ("gr::io_signature(1)");
if(sizeof_stream_items.size() < 1)
throw std::invalid_argument("gr::io_signature(2)");
for(size_t i = 0; i < sizeof_stream_items.size(); i++) {
if(max_streams != 0 && sizeof_stream_items[i] < 1)
throw std::invalid_argument("gr::io_signature(3)");
}
d_min_streams = min_streams;
d_max_streams = max_streams;
d_sizeof_stream_item = sizeof_stream_items;
}
io_signature::~io_signature()
{
}
int
io_signature::sizeof_stream_item(int _index) const
{
if(_index < 0)
throw std::invalid_argument("gr::io_signature::sizeof_stream_item");
size_t index = _index;
return d_sizeof_stream_item[std::min(index, d_sizeof_stream_item.size() - 1)];
}
std::vector<int>
io_signature::sizeof_stream_items() const
{
return d_sizeof_stream_item;
}
} /* namespace gr */

View File

@ -0,0 +1,189 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "local_sighandler.h"
#include <stdexcept>
#include <stdio.h>
#include <string.h>
namespace gr {
local_sighandler::local_sighandler(int signum,
void (*new_handler)(int))
: d_signum(signum)
{
#ifdef HAVE_SIGACTION
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = new_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
if(sigaction (d_signum, &new_action, &d_old_action) < 0) {
perror("sigaction (install new)");
throw std::runtime_error("sigaction");
}
#endif
}
local_sighandler::~local_sighandler()
{
#ifdef HAVE_SIGACTION
if(sigaction (d_signum, &d_old_action, 0) < 0) {
perror("sigaction (restore old)");
throw std::runtime_error("sigaction");
}
#endif
}
void
local_sighandler::throw_signal(int signum)
{
throw signal(signum);
}
/*
* Semi-hideous way to may a signal number into a signal name
*/
#define SIGNAME(x) case x: return #x
std::string
signal::name() const
{
char tmp[128];
switch(signum()) {
#ifdef SIGHUP
SIGNAME(SIGHUP);
#endif
#ifdef SIGINT
SIGNAME(SIGINT);
#endif
#ifdef SIGQUIT
SIGNAME(SIGQUIT);
#endif
#ifdef SIGILL
SIGNAME(SIGILL);
#endif
#ifdef SIGTRAP
SIGNAME(SIGTRAP);
#endif
#ifdef SIGABRT
SIGNAME(SIGABRT);
#endif
#ifdef SIGBUS
SIGNAME(SIGBUS);
#endif
#ifdef SIGFPE
SIGNAME(SIGFPE);
#endif
#ifdef SIGKILL
SIGNAME(SIGKILL);
#endif
#ifdef SIGUSR1
SIGNAME(SIGUSR1);
#endif
#ifdef SIGSEGV
SIGNAME(SIGSEGV);
#endif
#ifdef SIGUSR2
SIGNAME(SIGUSR2);
#endif
#ifdef SIGPIPE
SIGNAME(SIGPIPE);
#endif
#ifdef SIGALRM
SIGNAME(SIGALRM);
#endif
#ifdef SIGTERM
SIGNAME(SIGTERM);
#endif
#ifdef SIGSTKFLT
SIGNAME(SIGSTKFLT);
#endif
#ifdef SIGCHLD
SIGNAME(SIGCHLD);
#endif
#ifdef SIGCONT
SIGNAME(SIGCONT);
#endif
#ifdef SIGSTOP
SIGNAME(SIGSTOP);
#endif
#ifdef SIGTSTP
SIGNAME(SIGTSTP);
#endif
#ifdef SIGTTIN
SIGNAME(SIGTTIN);
#endif
#ifdef SIGTTOU
SIGNAME(SIGTTOU);
#endif
#ifdef SIGURG
SIGNAME(SIGURG);
#endif
#ifdef SIGXCPU
SIGNAME(SIGXCPU);
#endif
#ifdef SIGXFSZ
SIGNAME(SIGXFSZ);
#endif
#ifdef SIGVTALRM
SIGNAME(SIGVTALRM);
#endif
#ifdef SIGPROF
SIGNAME(SIGPROF);
#endif
#ifdef SIGWINCH
SIGNAME(SIGWINCH);
#endif
#ifdef SIGIO
SIGNAME(SIGIO);
#endif
#ifdef SIGPWR
SIGNAME(SIGPWR);
#endif
#ifdef SIGSYS
SIGNAME(SIGSYS);
#endif
default:
#if defined (HAVE_SNPRINTF)
#if defined (SIGRTMIN) && defined (SIGRTMAX)
if(signum() >= SIGRTMIN && signum() <= SIGRTMAX) {
snprintf(tmp, sizeof(tmp), "SIGRTMIN + %d", signum());
return tmp;
}
#endif
snprintf(tmp, sizeof(tmp), "SIGNAL %d", signum());
return tmp;
#else
return "Unknown signal";
#endif
}
}
} /* namespace gr */

View File

@ -0,0 +1,74 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_LOCAL_SIGHANDLER_H
#define INCLUDED_GR_LOCAL_SIGHANDLER_H
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <gnuradio/api.h>
#include <string>
namespace gr {
/*!
* \brief Get and set signal handler.
*
* \ingroup internal
* Constructor installs new handler, destructor reinstalls
* original value.
*/
class GR_RUNTIME_API local_sighandler
{
private:
int d_signum;
#ifdef HAVE_SIGACTION
struct sigaction d_old_action;
#endif
public:
local_sighandler(int signum, void (*new_handler)(int));
~local_sighandler();
/* throw gr_signal (signum) */
static void throw_signal(int signum);
};
/*!
* \brief Representation of signal.
*/
class GR_RUNTIME_API signal
{
private:
int d_signum;
public:
signal(int signum) : d_signum(signum) {}
int signum() const { return d_signum; }
std::string name() const;
};
} /* namespace gr */
#endif /* INCLUDED_GR_LOCAL_SIGHANDLER_H */

323
lib/runtime/logger.cc Normal file
View File

@ -0,0 +1,323 @@
/* -*- c++ -*- */
/*
* Copyright 2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*******************************************************************************
* Author: Mark Plett
* Description:
* The gr_log module wraps the log4cpp library for logging in gnuradio.
*******************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/logger.h>
#include <stdexcept>
#include <algorithm>
#ifdef ENABLE_GR_LOG
#ifdef HAVE_LOG4CPP
namespace gr {
bool logger_config::logger_configured(false);
/************************ BEGIN LOG4CPP HELPERS ***********************/
/* Logger config class. This is a singleton that controls how
* log4cpp is configured If watch_period>0 a thread is started to
* watch teh config file for changes.
*/
// Getters of logger_config
logger_config&
logger_config::get_instance(void)
{
static logger_config instance;
return instance;
}
std::string
logger_config::get_filename()
{
logger_config& in=get_instance();
return in.filename;
}
unsigned int
logger_config::get_watch_period()
{
logger_config& in=get_instance();
return in.watch_period;
}
// Method to watch config file for changes
void
logger_config::watch_file(std::string filename, unsigned int watch_period)
{
std::time_t last_write(boost::filesystem::last_write_time(filename));
std::time_t current_time(0);
while(true) {
try {
current_time = boost::filesystem::last_write_time(filename);
if(current_time>last_write) {
//std::cout<<"GNURadio Reloading logger configuration:"<<filename<<std::endl;
last_write = current_time;
// Should we wipe out all old configuration or just add the
// new? Just adding... logger_reset_config();
logger_configured = logger_load_config(filename);
}
boost::this_thread::sleep(boost::posix_time::time_duration(0,0,watch_period,0));
}
catch(const boost::thread_interrupted&) {
std::cout<<"GNURadio leaving logger config file watch."<<std::endl;
break;
}
}
}
// Method to load the confifuration. It only loads if the filename
// or watch has changed
void
logger_config::load_config(std::string filename,unsigned int watch_period)
{
logger_config& instance = get_instance();
// Only reconfigure if filename or watch has changed
if(!logger_configured) {
instance.filename = filename;
instance.watch_period = watch_period;
// Stop any file watching thread
if(instance.watch_thread!=NULL)
stop_watch();
// Load configuration
//std::cout<<"GNURadio Loading logger configuration:"<<instance.filename<<std::endl;
logger_configured = logger_load_config(instance.filename);
// Start watch if required
if(instance.watch_period>0) {
instance.watch_thread = new boost::thread(watch_file, instance.filename,
instance.watch_period);
}
}
}
// Method to stop the watcher thread
void
logger_config::stop_watch()
{
logger_config& instance = get_instance();
if(instance.watch_thread) {
instance.watch_thread->interrupt();
instance.watch_thread->join();
delete(instance.watch_thread);
instance.watch_thread=NULL;
}
}
// Method to reset logger configuration
void
logger_config::reset_config(void)
{
logger_config& instance = get_instance();
stop_watch();
std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
std::vector<log4cpp::Category*>::iterator logger = loggers->begin();
// We can't destroy categories but we can neuter them by removing all appenders.
for(;logger!=loggers->end();logger++) {
(*logger)->removeAllAppenders();
}
instance.filename = std::string("");
instance.watch_period = 0;
logger_configured = false;
}
/***************** Functions to call log4cpp methods *************************/
logger_ptr
logger_get_logger(std::string name)
{
if(log4cpp::Category::exists(name)) {
logger_ptr logger = &log4cpp::Category::getInstance(name);
return logger;
}
else {
logger_ptr logger = &log4cpp::Category::getInstance(name);
logger->setPriority(log4cpp::Priority::NOTSET);
return logger;
}
}
bool
logger_load_config(const std::string &config_filename)
{
if(config_filename.size() != 0) {
try {
log4cpp::PropertyConfigurator::configure(config_filename);
return true;
}
catch(log4cpp::ConfigureFailure &e) {
std::cerr << "Logger config failed :" << e.what() << std::endl;
}
}
return false;
}
void
logger_set_level(logger_ptr logger, const std::string &level)
{
std::string nocase = level;
std::transform(level.begin(), level.end(), nocase.begin(), ::tolower);
if(nocase == "off" || nocase == "notset")
logger_set_level(logger, log4cpp::Priority::NOTSET);
else if(nocase == "all" || nocase == "debug")
logger_set_level(logger, log4cpp::Priority::DEBUG);
else if(nocase == "info")
logger_set_level(logger, log4cpp::Priority::INFO);
else if(nocase == "notice")
logger_set_level(logger, log4cpp::Priority::NOTICE);
else if(nocase == "warn")
logger_set_level(logger, log4cpp::Priority::WARN);
else if(nocase == "error")
logger_set_level(logger, log4cpp::Priority::ERROR);
else if(nocase == "crit")
logger_set_level(logger, log4cpp::Priority::CRIT);
else if(nocase == "alert")
logger_set_level(logger, log4cpp::Priority::ALERT);
else if(nocase=="fatal")
logger_set_level(logger, log4cpp::Priority::FATAL);
else if(nocase == "emerg")
logger_set_level(logger, log4cpp::Priority::EMERG);
else
throw std::runtime_error("logger_set_level: Bad level type.\n");
}
void
logger_set_level(logger_ptr logger, log4cpp::Priority::Value level)
{
logger->setPriority(level);
}
void
logger_get_level(logger_ptr logger, std::string &level)
{
log4cpp::Priority::Value levelPtr = logger->getPriority();
if(levelPtr == log4cpp::Priority::NOTSET) level = "noset";
if(levelPtr == log4cpp::Priority::DEBUG) level = "debug";
if(levelPtr == log4cpp::Priority::INFO) level = "info";
if(levelPtr == log4cpp::Priority::NOTICE) level = "notice";
if(levelPtr == log4cpp::Priority::WARN) level = "warn";
if(levelPtr == log4cpp::Priority::ERROR) level = "error";
if(levelPtr == log4cpp::Priority::CRIT) level = "crit";
if(levelPtr == log4cpp::Priority::ALERT) level = "alert";
if(levelPtr == log4cpp::Priority::FATAL) level = "fatal";
if(levelPtr == log4cpp::Priority::EMERG) level = "emerg";
}
void
logger_get_level(logger_ptr logger,log4cpp::Priority::Value level)
{
level = logger->getPriority();
}
void
logger_add_console_appender(logger_ptr logger, std::string target, std::string pattern)
{
log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
log4cpp::Appender* app;
if(target=="stdout")
app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cout);
else
app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cerr);
layout->setConversionPattern(pattern);
app->setLayout(layout);
logger->setAppender(*app);
}
void
logger_add_file_appender(logger_ptr logger, std::string filename,
bool append, std::string pattern)
{
log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
log4cpp::Appender* app = new
log4cpp::FileAppender("FileAppender::"+filename,
filename);
layout->setConversionPattern(pattern);
app->setLayout(layout);
logger->setAppender(app);
}
void
logger_add_rollingfile_appender(logger_ptr logger, std::string filename,
size_t filesize, int bkup_index, bool append,
mode_t mode, std::string pattern)
{
log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
log4cpp::Appender* app = new
log4cpp::RollingFileAppender("RollFileAppender::" + filename, filename,
filesize, bkup_index, append, mode);
layout->setConversionPattern(pattern);
app->setLayout(layout);
logger->setAppender(app);
}
std::vector<std::string>
logger_get_logger_names(void)
{
std::vector<std::string> names;
std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
std::vector<log4cpp::Category*>::iterator logger = loggers->begin();
for(;logger!=loggers->end();logger++) {
names.push_back((*logger)->getName());
}
return names;
}
} /* namespace gr */
#endif /* HAVE_LOG4CPP */
/****** Start Methods to provide Python the capabilities of the macros ********/
void
gr_logger_config(const std::string config_filename, unsigned int watch_period)
{
GR_CONFIG_AND_WATCH_LOGGER(config_filename, watch_period);
}
std::vector<std::string>
gr_logger_get_logger_names(void)
{
std::vector<std::string> names;
GR_GET_LOGGER_NAMES(names);
return names;
}
void
gr_logger_reset_config(void)
{
GR_RESET_CONFIGURATION();
}
// Remaining capability provided by gr::logger class in gnuradio/logger.h
#endif /* ENABLE_GR_LOGGER */

View File

@ -0,0 +1,202 @@
/* -*- c++ -*- */
/*
* Copyright 2005,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <gnuradio/math.h> // declaration is in here
#include <cmath>
namespace gr {
/***************************************************************************/
/* Constant definitions */
/***************************************************************************/
#define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */
#define RAD_PER_DEG 0.017453293
#define TAN_MAP_SIZE 256
/* arctangents from 0 to pi/4 radians */
static float
fast_atan_table[257] = {
0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02,
1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02,
3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02,
4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02,
6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02,
7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02,
9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01,
1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01,
1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01,
1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01,
1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01,
1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01,
1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01,
2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01,
2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01,
2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01,
2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01,
2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01,
2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01,
2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01,
3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01,
3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01,
3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01,
3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01,
3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01,
3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01,
3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01,
4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01,
4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01,
4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01,
4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01,
4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01,
4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01,
4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01,
4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01,
5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01,
5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01,
5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01,
5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01,
5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01,
5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01,
5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01,
5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01,
5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01,
6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01,
6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01,
6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01,
6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01,
6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01,
6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01,
6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01,
6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01,
6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01,
6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01,
7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01,
7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01,
7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01,
7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01,
7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01,
7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01,
7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01,
7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01,
7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01,
7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01,
7.853983e-01
};
/*****************************************************************************
Function: Arc tangent
Syntax: angle = fast_atan2(y, x);
float y y component of input vector
float x x component of input vector
float angle angle of vector (x, y) in radians
Description: This function calculates the angle of the vector (x,y)
based on a table lookup and linear interpolation. The table uses a
256 point table covering -45 to +45 degrees and uses symetry to
determine the final angle value in the range of -180 to 180
degrees. Note that this function uses the small angle approximation
for values close to zero. This routine calculates the arc tangent
with an average error of +/- 0.045 degrees.
*****************************************************************************/
float
fast_atan2f(float y, float x)
{
float x_abs, y_abs, z;
float alpha, angle, base_angle;
int index;
/* don't divide by zero! */ // FIXME could get hosed with -0.0
if((y == 0.0) && (x == 0.0))
return 0.0;
/* normalize to +/- 45 degree range */
y_abs = fabsf(y);
x_abs = fabsf(x);
//z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs);
if(y_abs < x_abs)
z = y_abs / x_abs;
else
z = x_abs / y_abs;
/* when ratio approaches the table resolution, the angle is */
/* best approximated with the argument itself... */
if(z < TAN_MAP_RES)
base_angle = z;
else {
/* find index and interpolation value */
alpha = z * (float)TAN_MAP_SIZE - .5;
index = (int)alpha;
alpha -= (float)index;
/* determine base angle based on quadrant and */
/* add or subtract table value from base angle based on quadrant */
base_angle = fast_atan_table[index];
base_angle +=
(fast_atan_table[index + 1] - fast_atan_table[index]) * alpha;
}
if(x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */
if(x >= 0.0) { /* -45 -> 45 */
if(y >= 0.0)
angle = base_angle; /* 0 -> 45, angle OK */
else
angle = -base_angle; /* -45 -> 0, angle = -angle */
}
else { /* 135 -> 180 or 180 -> -135 */
angle = 3.14159265358979323846;
if(y >= 0.0)
angle -= base_angle; /* 135 -> 180, angle = 180 - angle */
else
angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */
}
}
else { /* 45 -> 135 or -135 -> -45 */
if(y >= 0.0) { /* 45 -> 135 */
angle = 1.57079632679489661923;
if(x >= 0.0)
angle -= base_angle; /* 45 -> 90, angle = 90 - angle */
else
angle += base_angle; /* 90 -> 135, angle = 90 + angle */
}
else { /* -135 -> -45 */
angle = -1.57079632679489661923;
if(x >= 0.0)
angle += base_angle; /* -90 -> -45, angle = -90 + angle */
else
angle -= base_angle; /* -135 -> -90, angle = -90 - angle */
}
}
#ifdef ZERO_TO_TWOPI
if (angle < 0)
return (angle + TWOPI);
else
return (angle);
#else
return (angle);
#endif
}
} /* namespace gr */

38
lib/runtime/math/fxpt.cc Normal file
View File

@ -0,0 +1,38 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/fxpt.h>
namespace gr {
const float fxpt::s_sine_table[1 << NBITS][2] = {
#include "sine_table.h"
};
const float fxpt::PI = 3.14159265358979323846;
const float fxpt::TWO_TO_THE_31 = 2147483648.0;
} /* namespace gr */

188
lib/runtime/math/random.cc Normal file
View File

@ -0,0 +1,188 @@
/* -*- c++ -*- */
/*
* Copyright 2002 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*
* Copyright 1997 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <math.h>
#include <gnuradio/random.h>
namespace gr {
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
random::random(long seed)
{
reseed(seed);
}
void
random::reseed(long seed)
{
d_seed = seed;
d_iy = 0;
for(int i = 0; i < NTAB; i++)
d_iv[i] = 0;
d_iset = 0;
d_gset = 0;
}
/*
* This looks like it returns a uniform random deviate between 0.0 and 1.0
* It looks similar to code from "Numerical Recipes in C".
*/
float
random::ran1()
{
int j;
long k;
float temp;
if(d_seed <= 0 || !d_iy) {
if(-d_seed < 1)
d_seed=1;
else
d_seed = -d_seed;
for(j=NTAB+7;j>=0;j--) {
k=d_seed/IQ;
d_seed=IA*(d_seed-k*IQ)-IR*k;
if(d_seed < 0)
d_seed += IM;
if(j < NTAB)
d_iv[j] = d_seed;
}
d_iy=d_iv[0];
}
k=(d_seed)/IQ;
d_seed=IA*(d_seed-k*IQ)-IR*k;
if(d_seed < 0)
d_seed += IM;
j=d_iy/NDIV;
d_iy=d_iv[j];
d_iv[j] = d_seed;
temp=AM * d_iy;
if(temp > RNMX)
temp = RNMX;
return temp;
}
/*
* Returns a normally distributed deviate with zero mean and variance 1.
* Also looks like it's from "Numerical Recipes in C".
*/
float
random::gasdev()
{
float fac,rsq,v1,v2;
d_iset = 1 - d_iset;
if(d_iset) {
do {
v1=2.0*ran1()-1.0;
v2=2.0*ran1()-1.0;
rsq=v1*v1+v2*v2;
} while(rsq >= 1.0 || rsq == 0.0);
fac= sqrt(-2.0*log(rsq)/rsq);
d_gset=v1*fac;
return v2*fac;
}
return d_gset;
}
/*
* Copied from The KC7WW / OH2BNS Channel Simulator
* FIXME Need to check how good this is at some point
*/
float
random::laplacian()
{
float z = ran1();
if(z < 0.5)
return log(2.0 * z) / M_SQRT2;
else
return -log(2.0 * (1.0 - z)) / M_SQRT2;
}
/*
* Copied from The KC7WW / OH2BNS Channel Simulator
* FIXME Need to check how good this is at some point
*/
// 5 => scratchy, 8 => Geiger
float
random::impulse(float factor = 5)
{
float z = -M_SQRT2 * log(ran1());
if(fabsf(z) <= factor)
return 0.0;
else
return z;
}
/*
* Complex rayleigh is really gaussian I and gaussian Q
* It can also be generated by real rayleigh magnitude and
* uniform random angle
* Adapted from The KC7WW / OH2BNS Channel Simulator
* FIXME Need to check how good this is at some point
*/
gr_complex
random::rayleigh_complex()
{
return gr_complex(gasdev(),gasdev());
}
/* Other option
mag = rayleigh();
ang = 2.0 * M_PI * RNG();
*Rx = rxx * cos(z);
*Iy = rxx * sin(z);
*/
float
random::rayleigh()
{
return sqrt(-2.0 * log(ran1()));
}
} /* namespace gr */

View File

@ -0,0 +1,85 @@
/* -*- c++ -*- */
/*
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // ask for GNU extensions if available
#endif
#include <gnuradio/sincos.h>
#include <math.h>
namespace gr {
#if defined (HAVE_SINCOS)
void
sincos(double x, double *sinx, double *cosx)
{
::sincos(x, sinx, cosx);
}
#else
void
sincos(double x, double *sinx, double *cosx)
{
*sinx = ::sin(x);
*cosx = ::cos(x);
}
#endif
// ----------------------------------------------------------------
#if defined (HAVE_SINCOSF)
void
sincosf(float x, float *sinx, float *cosx)
{
::sincosf(x, sinx, cosx);
}
#elif defined (HAVE_SINF) && defined (HAVE_COSF)
void
sincosf(float x, float *sinx, float *cosx)
{
*sinx = ::sinf(x);
*cosx = ::cosf(x);
}
#else
void
sincosf(float x, float *sinx, float *cosx)
{
*sinx = ::sin(x);
*cosx = ::cos(x);
}
#endif
} /* namespace gr */

File diff suppressed because it is too large Load Diff

99
lib/runtime/math/vco.h Normal file
View File

@ -0,0 +1,99 @@
/* -*- c++ -*- */
/*
* Copyright 2005,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef _GR_VCO_H_
#define _GR_VCO_H_
#include <gnuradio/sincos.h>
#include <gnuradio/gr_complex.h>
#include <vector>
#include <cmath>
namespace gr {
/*!
* \brief base class template for Voltage Controlled Oscillator (VCO)
* \ingroup misc
*/
template<class o_type, class i_type>
class vco
{
public:
vco() : d_phase(0) {}
virtual ~vco() {}
// radians
void set_phase(double angle) {
d_phase = angle;
}
void adjust_phase(double delta_phase) {
d_phase += delta_phase;
if(fabs (d_phase) > M_PI){
while(d_phase > M_PI)
d_phase -= 2*M_PI;
while(d_phase < -M_PI)
d_phase += 2*M_PI;
}
}
double get_phase() const { return d_phase; }
// compute sin and cos for current phase angle
void sincos(float *sinx, float *cosx) const;
// compute cos or sin for current phase angle
float cos() const { return std::cos(d_phase); }
float sin() const { return std::sin(d_phase); }
// compute a block at a time
void cos(float *output, const float *input,
int noutput_items, double k, double ampl = 1.0);
protected:
double d_phase;
};
template<class o_type, class i_type>
void
vco<o_type,i_type>::sincos(float *sinx, float *cosx) const
{
gr::sincosf(d_phase, sinx, cosx);
}
template<class o_type, class i_type>
void
vco<o_type,i_type>::cos(float *output, const float *input,
int noutput_items, double k, double ampl)
{
for(int i = 0; i < noutput_items; i++) {
output[i] = cos() * ampl;
adjust_phase(input[i] * k);
}
}
} /* namespace gr */
#endif /* _GR_VCO_H_ */

70
lib/runtime/misc.cc Normal file
View File

@ -0,0 +1,70 @@
/* -*- c++ -*- */
/*
* Copyright 2005,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "misc.h"
namespace gr {
unsigned int
rounduppow2(unsigned int n)
{
int i;
for(i=0;((n-1)>>i) != 0;i++)
;
return 1<<i;
}
// ----------------------------------------------------------------
void
zero_vector(std::vector<float> &v)
{
for(unsigned int i=0; i < v.size(); i++)
v[i] = 0;
}
void
zero_vector(std::vector<double> &v)
{
for(unsigned int i=0; i < v.size(); i++)
v[i] = 0;
}
void
zero_vector(std::vector<int> &v)
{
for(unsigned int i=0; i < v.size(); i++)
v[i] = 0;
}
void
zero_vector(std::vector<gr_complex> &v)
{
for(unsigned int i=0; i < v.size(); i++)
v[i] = 0;
}
} /* namespace gr */

42
lib/runtime/misc.h Normal file
View File

@ -0,0 +1,42 @@
/* -*- c++ -*- */
/*
* Copyright 2005,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_MISC_H
#define INCLUDED_GR_MISC_H
#include <gnuradio/api.h>
#include <gnuradio/types.h>
namespace gr {
GR_RUNTIME_API unsigned int
rounduppow2(unsigned int n);
// FIXME should be template
GR_RUNTIME_API void zero_vector(std::vector<float> &v);
GR_RUNTIME_API void zero_vector(std::vector<double> &v);
GR_RUNTIME_API void zero_vector(std::vector<int> &v);
GR_RUNTIME_API void zero_vector(std::vector<gr_complex> &v);
} /* namespace gr */
#endif /* INCLUDED_GR_MISC_H */

59
lib/runtime/pagesize.cc Normal file
View File

@ -0,0 +1,59 @@
/* -*- c++ -*- */
/*
* Copyright 2003,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "pagesize.h"
#include <unistd.h>
#include <stdio.h>
namespace gr {
#if defined(_WIN32) && defined(HAVE_GETPAGESIZE)
extern "C" size_t getpagesize(void);
#endif
int
pagesize()
{
static int s_pagesize = -1;
if(s_pagesize == -1) {
#if defined(HAVE_GETPAGESIZE)
s_pagesize = getpagesize();
#elif defined (HAVE_SYSCONF)
s_pagesize = sysconf(_SC_PAGESIZE);
if(s_pagesize == -1) {
perror("_SC_PAGESIZE");
s_pagesize = 4096;
}
#else
fprintf(stderr, "gr::pagesize: no info; setting pagesize = 4096\n");
s_pagesize = 4096;
#endif
}
return s_pagesize;
}
} /* namespace gr */

37
lib/runtime/pagesize.h Normal file
View File

@ -0,0 +1,37 @@
/* -*- c++ -*- */
/*
* Copyright 2003,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef GR_PAGESIZE_H_
#define GR_PAGESIZE_H_
#include <gnuradio/api.h>
namespace gr {
/*!
* \brief return the page size in bytes
*/
GR_RUNTIME_API int pagesize();
} /* namespace gr */
#endif /* GR_PAGESIZE_H_ */

View File

@ -0,0 +1,114 @@
/* -*- c++ -*- */
/*
* Copyright 2008,2009 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "posix_memalign.h"
#ifdef HAVE_MALLOC_H
// for Cygwin valloc () prototype
#include <malloc.h>
#endif
#ifndef HAVE_POSIX_MEMALIGN
/* emulate posix_memalign functionality, to some degree */
#include <errno.h>
#include "pagesize.h"
int posix_memalign
(void **memptr, size_t alignment, size_t size)
{
/* emulate posix_memalign functionality, to some degree */
/* make sure the return handle is valid; return "bad address" if not valid */
if (memptr == 0)
return (EFAULT);
*memptr = (void*) 0;
/* make sure 'alignment' is a power of 2
* and multiple of sizeof (void*)
*/
/* make sure 'alignment' is a multiple of sizeof (void*) */
if ((alignment % sizeof (void*)) != 0)
return (EINVAL);
/* make sure 'alignment' is a power of 2 */
if ((alignment & (alignment - 1)) != 0)
return (EINVAL);
/* good alignment */
#if (ALIGNED_MALLOC != 0)
/* if 'malloc' is known to be aligned, and the desired 'alignment'
* matches is <= that provided by 'malloc', then use 'malloc'. This
* works on, e.g., Darwin 8 & 9: for which malloc is 16-byte aligned.
*/
size_t am = (size_t) ALIGNED_MALLOC;
if (alignment <= am) {
/* make sure ALIGNED_MALLOC is a power of 2, to guarantee that the
* alignment is correct (since 'alignment' must be a power of 2).
*/
if ((am & (am - 1)) != 0)
return (EINVAL);
/* good malloc alignment */
*memptr = malloc (size);
}
#endif /* (ALIGNED_MALLOC != 0) */
#ifdef HAVE_VALLOC
if (*memptr == (void*) 0) {
/* try valloc if it exists */
/* cheap and easy way to make sure alignment is met, so long as it
* is <= pagesize () */
if (alignment <= (size_t) gr::pagesize ()) {
*memptr = valloc (size);
}
}
#endif /* HAVE_VALLOC */
#if (ALIGNED_MALLOC == 0) && !defined (HAVE_VALLOC)
/* no posix_memalign, valloc, and malloc isn't known to be aligned
* (enough for the input arguments); no idea what to do.
*/
#error gnuradio-runtime/lib/posix_memalign.cc: Cannot find a way to alloc aligned memory.
#endif
/* if the pointer wasn't allocated properly, return that there was
* not enough memory to allocate; otherwise, return OK (0).
*/
if (*memptr == (void*) 0)
return (ENOMEM);
else
return (0);
};
#endif /* ! HAVE_POSIX_MEMALIGN */

View File

@ -0,0 +1,42 @@
/* -*- c++ -*- */
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef _POSIX_MEMALIGN_H_
#define _POSIX_MEMALIGN_H_
#include <stdlib.h>
#ifndef HAVE_POSIX_MEMALIGN
#ifdef __cplusplus
extern "C" {
#endif
extern int posix_memalign (void** memptr, size_t alignment, size_t size);
#ifdef __cplusplus
};
#endif
#endif /* ! HAVE_POSIX_MEMALIGN */
#endif /* _POSIX_MEMALIGN_H_ */

401
lib/runtime/prefs.cc Normal file
View File

@ -0,0 +1,401 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnuradio/prefs.h>
#include <gnuradio/sys_paths.h>
#include <gnuradio/constants.h>
#include <algorithm>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
namespace fs = boost::filesystem;
namespace gr {
/*
* Stub implementations
*/
static prefs s_default_singleton;
static prefs *s_singleton = &s_default_singleton;
prefs *
prefs::singleton()
{
return s_singleton;
}
void
prefs::set_singleton(prefs *p)
{
s_singleton = p;
}
prefs::prefs()
{
_read_files();
}
prefs::~prefs()
{
// nop
}
std::vector<std::string>
prefs::_sys_prefs_filenames()
{
std::vector<std::string> fnames;
fs::path dir = prefsdir();
if(!fs::is_directory(dir))
return fnames;
fs::directory_iterator diritr(dir);
while(diritr != fs::directory_iterator()) {
fs::path p = *diritr++;
if(p.extension() != ".swp")
fnames.push_back(p.string());
}
std::sort(fnames.begin(), fnames.end());
// Find if there is a ~/.gnuradio/config.conf file and add this to
// the end of the file list to override any preferences in the
// installed path config files.
fs::path homedir = fs::path(gr::appdata_path());
homedir = homedir/".gnuradio/config.conf";
if(fs::exists(homedir)) {
fnames.push_back(homedir.string());
}
return fnames;
}
void
prefs::_read_files()
{
std::string config;
std::vector<std::string> filenames = _sys_prefs_filenames();
std::vector<std::string>::iterator sitr;
char tmp[1024];
for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) {
fs::ifstream fin(*sitr);
while(!fin.eof()) {
fin.getline(tmp, 1024);
std::string t(tmp);
// ignore empty lines or lines of just comments
if((t.size() > 0) && (t[0] != '#')) {
// remove any comments in the line
size_t hash = t.find("#");
// Use hash marks at the end of each segment as a delimiter
config += t.substr(0, hash) + '#';
}
}
fin.close();
}
// Remove all whitespace.
config.erase(std::remove_if(config.begin(), config.end(),
::isspace), config.end());
// Convert the string into a map
_convert_to_map(config);
}
void
prefs::_convert_to_map(const std::string &conf)
{
// Convert the string into an map of maps
// Map is structured as {section name: map of options}
// And options map is simply: {option name: option value}
std::string sub = conf;
size_t sec_start = sub.find("[");
while(sec_start != std::string::npos) {
sub = sub.substr(sec_start);
size_t sec_end = sub.find("]");
if(sec_end == std::string::npos)
throw std::runtime_error("Config file error: Mismatched section label.\n");
std::string sec = sub.substr(1, sec_end-1);
size_t next_sec_start = sub.find("[", sec_end);
std::string subsec = sub.substr(sec_end+1, next_sec_start-sec_end-2);
std::transform(sec.begin(), sec.end(), sec.begin(), ::tolower);
std::map<std::string, std::string> options_map = d_config_map[sec];
size_t next_opt = 0;
size_t next_val = 0;
next_opt = subsec.find("#");
while(next_opt < subsec.size()-1) {
next_val = subsec.find("=", next_opt);
std::string option = subsec.substr(next_opt+1, next_val-next_opt-1);
next_opt = subsec.find("#", next_val);
std::string value = subsec.substr(next_val+1, next_opt-next_val-1);
std::transform(option.begin(), option.end(), option.begin(), ::tolower);
options_map[option] = value;
}
d_config_map[sec] = options_map;
sec_start = sub.find("[", sec_end);
}
}
std::string
prefs::to_string()
{
config_map_itr sections;
config_map_elem_itr options;
std::stringstream s;
for(sections = d_config_map.begin(); sections != d_config_map.end(); sections++) {
s << "[" << sections->first << "]" << std::endl;
for(options = sections->second.begin(); options != sections->second.end(); options++) {
s << options->first << " = " << options->second << std::endl;
}
s << std::endl;
}
return s.str();
}
void
prefs::save()
{
std::string conf = to_string();
fs::path homedir = fs::path(gr::appdata_path());
homedir = homedir/".gnuradio/config.conf";
fs::ofstream fout(homedir);
fout << conf;
fout.close();
}
char *
prefs::option_to_env(std::string section, std::string option)
{
std::stringstream envname;
std::string secname=section, optname=option;
std::transform(section.begin(), section.end(), secname.begin(), ::toupper);
std::transform(option.begin(), option.end(), optname.begin(), ::toupper);
envname << "GR_CONF_" << secname << "_" << optname;
return getenv(envname.str().c_str());
}
bool
prefs::has_section(const std::string &section)
{
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
return d_config_map.count(s) > 0;
}
bool
prefs::has_option(const std::string &section, const std::string &option)
{
if(option_to_env(section, option))
return true;
if(has_section(section)) {
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
config_map_itr sec = d_config_map.find(s);
return sec->second.count(o) > 0;
}
else {
return false;
}
}
const std::string
prefs::get_string(const std::string &section, const std::string &option,
const std::string &default_val)
{
char *env = option_to_env(section, option);
if(env)
return std::string(env);
if(has_option(section, option)) {
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
config_map_itr sec = d_config_map.find(s);
config_map_elem_itr opt = sec->second.find(o);
return opt->second;
}
else {
return default_val;
}
}
void
prefs::set_string(const std::string &section, const std::string &option,
const std::string &val)
{
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
std::map<std::string, std::string> opt_map = d_config_map[s];
opt_map[o] = val;
d_config_map[s] = opt_map;
}
bool
prefs::get_bool(const std::string &section, const std::string &option,
bool default_val)
{
if(has_option(section, option)) {
std::string str = get_string(section, option, "");
if(str == "") {
return default_val;
}
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if((str == "true") || (str == "on") || (str == "1"))
return true;
else if((str == "false") || (str == "off") || (str == "0"))
return false;
else
return default_val;
}
else {
return default_val;
}
}
void
prefs::set_bool(const std::string &section, const std::string &option,
bool val)
{
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
std::map<std::string, std::string> opt_map = d_config_map[s];
std::stringstream sstr;
sstr << (val == true);
opt_map[o] = sstr.str();
d_config_map[s] = opt_map;
}
long
prefs::get_long(const std::string &section, const std::string &option,
long default_val)
{
if(has_option(section, option)) {
std::string str = get_string(section, option, "");
if(str == "") {
return default_val;
}
std::stringstream sstr(str);
long n;
sstr >> n;
return n;
}
else {
return default_val;
}
}
void
prefs::set_long(const std::string &section, const std::string &option,
long val)
{
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
std::map<std::string, std::string> opt_map = d_config_map[s];
std::stringstream sstr;
sstr << val;
opt_map[o] = sstr.str();
d_config_map[s] = opt_map;
}
double
prefs::get_double(const std::string &section, const std::string &option,
double default_val)
{
if(has_option(section, option)) {
std::string str = get_string(section, option, "");
if(str == "") {
return default_val;
}
std::stringstream sstr(str);
double n;
sstr >> n;
return n;
}
else {
return default_val;
}
}
void
prefs::set_double(const std::string &section, const std::string &option,
double val)
{
std::string s = section;
std::transform(section.begin(), section.end(), s.begin(), ::tolower);
std::string o = option;
std::transform(option.begin(), option.end(), o.begin(), ::tolower);
std::map<std::string, std::string> opt_map = d_config_map[s];
std::stringstream sstr;
sstr << val;
opt_map[o] = sstr.str();
d_config_map[s] = opt_map;
}
} /* namespace gr */

37
lib/runtime/realtime.cc Normal file
View File

@ -0,0 +1,37 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnuradio/realtime.h>
namespace gr {
rt_status_t
enable_realtime_scheduling()
{
return gr::impl::enable_realtime_scheduling();
}
} /* namespace gr */

Some files were not shown because too many files have changed in this diff Show More