Improvements on the overall structure of the project
* Improve performance of the Golay decoder * Modernize some CMake modules of GNU Radio * Re-introduce the CPPUnit automated tests
This commit is contained in:
parent
8625475fd9
commit
9fe6b6f274
|
@ -1,8 +1,30 @@
|
|||
variables:
|
||||
GITLAB_CI_IMAGE_DEBIAN: 'debian:buster'
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
test:
|
||||
stage: test
|
||||
before_script:
|
||||
- apt-get update -qq && apt-get install -y -qq gnuradio-dev libcppunit-dev libpng++-dev libvorbis-dev cmake swig pkg-config build-essential git
|
||||
script:
|
||||
- mkdir -p build
|
||||
- cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
- make
|
||||
- make install
|
||||
- ldconfig
|
||||
- python -c "import satnogs"
|
||||
- rm -rf *
|
||||
- cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DINCLUDE_DEBUG_BLOCKS=OFF -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
- make
|
||||
- make CTEST_OUTPUT_ON_FAILURE=1 test
|
||||
- make install
|
||||
- ldconfig
|
||||
- python -c "import satnogs"
|
||||
|
||||
debian:
|
||||
stage: build
|
||||
image: ${GITLAB_CI_IMAGE_DEBIAN}
|
||||
|
|
|
@ -51,6 +51,22 @@ set(VERSION_INFO_API_COMPAT 5)
|
|||
set(VERSION_INFO_MINOR_VERSION 1)
|
||||
set(VERSION_INFO_MAINT_VERSION git)
|
||||
|
||||
# Set cmake policies.
|
||||
# This will suppress developer warnings during the cmake process that can occur
|
||||
# if a newer cmake version than the minimum is used.
|
||||
|
||||
if(POLICY CMP0026)
|
||||
cmake_policy(SET CMP0026 OLD)
|
||||
endif()
|
||||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 OLD)
|
||||
endif()
|
||||
if(POLICY CMP0045)
|
||||
cmake_policy(SET CMP0045 OLD)
|
||||
endif()
|
||||
if(POLICY CMP0046)
|
||||
cmake_policy(SET CMP0046 OLD)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
# Compiler specific setup
|
||||
|
@ -216,7 +232,6 @@ include_directories(
|
|||
${Boost_INCLUDE_DIRS}
|
||||
${CPPUNIT_INCLUDE_DIRS}
|
||||
${GNURADIO_ALL_INCLUDE_DIRS}
|
||||
${NOVA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
link_directories(
|
||||
|
|
|
@ -955,7 +955,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
# the new option.
|
||||
# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
|
||||
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
|
||||
# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
|
||||
# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
# Copyright (c) 2012 - 2017, Lars Bilke
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
#
|
||||
# CHANGES:
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# 2016-02-03, Lars Bilke
|
||||
# - Refactored functions to use named parameters
|
||||
#
|
||||
# 2017-06-02, Lars Bilke
|
||||
# - Merged with modified version from github.com/ufz/ogs
|
||||
#
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt:
|
||||
# include(CodeCoverage)
|
||||
#
|
||||
# 3. Append necessary compiler flags:
|
||||
# APPEND_COVERAGE_COMPILER_FLAGS()
|
||||
#
|
||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||
#
|
||||
# 4. If you need to exclude additional directories from the report, specify them
|
||||
# using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV.
|
||||
# Example:
|
||||
# set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*')
|
||||
#
|
||||
# 5. Use the functions described below to create a custom make target which
|
||||
# runs your test executable and produces a code coverage report.
|
||||
#
|
||||
# 6. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Check prereqs
|
||||
find_program( GCOV_PATH gcov )
|
||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||
find_program( GCOVR_PATH NAMES gcovr)
|
||||
find_program( PYTHON3_INTERP NAMES python3)
|
||||
|
||||
if(NOT PYTHON3_INTERP)
|
||||
message(FATAL_ERROR "python3 not found! Aborting...")
|
||||
endif()
|
||||
|
||||
if(NOT GCOV_PATH)
|
||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif() # NOT GCOV_PATH
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||
endif()
|
||||
elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||
message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||
endif()
|
||||
|
||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE INTERNAL "")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
mark_as_advanced(
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||
endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# Handy macro to set easily a vatriable with a list of exclude directories
|
||||
###############################################################################
|
||||
macro(COVERAGE_SET_EXCLUDE_DIRS var)
|
||||
set(${var} ${ARGN} CACHE INTERNAL "" FORCE)
|
||||
endmacro(COVERAGE_SET_EXCLUDE_DIRS)
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# SETUP_TARGET_FOR_COVERAGE_LCOV(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# )
|
||||
function(SETUP_TARGET_FOR_COVERAGE_LCOV)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT LCOV_PATH)
|
||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif() # NOT LCOV_PATH
|
||||
|
||||
if(NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif() # NOT GENHTML_PATH
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
|
||||
# Cleanup lcov
|
||||
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . --zerocounters
|
||||
# Create baseline to make sure untouched files show up in the report
|
||||
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
|
||||
|
||||
# Run tests
|
||||
COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
|
||||
# Capturing lcov counters and generating report
|
||||
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
|
||||
# add baseline counters
|
||||
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total
|
||||
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show where to find the lcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# SETUP_TARGET_FOR_COVERAGE_GCOVR_XML(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# )
|
||||
function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDES "")
|
||||
set(GCOVR_EXCLUDES_DIRS "")
|
||||
foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES})
|
||||
string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE})
|
||||
list(APPEND GCOVR_EXCLUDES "-e")
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}")
|
||||
endforeach()
|
||||
foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDE_DIRS})
|
||||
string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE})
|
||||
list(APPEND GCOVR_EXCLUDE_DIRS "--exclude-directories")
|
||||
list(APPEND GCOVR_EXCLUDE_DIRS "${EXCLUDE_REPLACED}")
|
||||
endforeach()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
# Run tests
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
|
||||
# Running gcovr
|
||||
COMMAND ${GCOVR_PATH} --xml
|
||||
-r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} ${GCOVR_EXCLUDE_DIRS}
|
||||
--object-directory=${PROJECT_BINARY_DIR}
|
||||
-o ${Coverage_NAME}.xml
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
||||
)
|
||||
|
||||
endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# )
|
||||
function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDES "")
|
||||
set(GCOVR_EXCLUDES_DIRS "")
|
||||
foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES})
|
||||
string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE})
|
||||
list(APPEND GCOVR_EXCLUDES "-e")
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}")
|
||||
endforeach()
|
||||
foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDE_DIRS})
|
||||
string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE})
|
||||
list(APPEND GCOVR_EXCLUDE_DIRS "--exclude-directories")
|
||||
list(APPEND GCOVR_EXCLUDE_DIRS "${EXCLUDE_REPLACED}")
|
||||
endforeach()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
# Run tests
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
|
||||
# Create folder
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
|
||||
|
||||
# Running gcovr
|
||||
|
||||
COMMAND ${PYTHON3_INTERP} ${GCOVR_PATH} --html --html-details
|
||||
-r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} ${GCOVR_EXCLUDE_DIRS}
|
||||
--object-directory=${PROJECT_BINARY_DIR}
|
||||
-o ${Coverage_NAME}/index.html
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Running gcovr to produce HTML code coverage report."
|
||||
|
||||
# Run it again to generate the report in text based form for the
|
||||
# CI to parse it
|
||||
COMMAND ${PYTHON3_INTERP} ${GCOVR_PATH}
|
||||
-r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} ${GCOVR_EXCLUDE_DIRS}
|
||||
--object-directory=${PROJECT_BINARY_DIR}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Running gcovr to produce HTML code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML
|
||||
|
||||
function(APPEND_COVERAGE_COMPILER_FLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction() # APPEND_COVERAGE_COMPILER_FLAGS
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright 2010-2011,2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
# This file was generated by gr_modtool, a tool from the GNU Radio framework
|
||||
# This file is a part of gr-ccsds
|
||||
#
|
||||
# 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
|
||||
|
@ -190,7 +191,7 @@ endfunction(GR_LIBRARY_FOO)
|
|||
# GR_GEN_TARGET_DEPS(unique_name target_deps <target1> <target2> ...)
|
||||
# ADD_CUSTOM_COMMAND(<the usual args> ${target_deps})
|
||||
#
|
||||
# Custom command cant depend on targets, but can depend on executables,
|
||||
# Custom command can't depend on targets, but can depend on executables,
|
||||
# and executables can depend on targets. So this is the process:
|
||||
########################################################################
|
||||
function(GR_GEN_TARGET_DEPS name var)
|
||||
|
@ -209,7 +210,7 @@ function(GR_GEN_TARGET_DEPS name var)
|
|||
endif(ARGN)
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross
|
||||
set(${var} "DEPENDS;${name}" PARENT_SCOPE) #can't call command when cross
|
||||
else()
|
||||
set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
@ -363,6 +364,7 @@ macro(GR_EXPAND_X_H component root)
|
|||
|
||||
import sys, os, re
|
||||
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
|
||||
sys.path.append('${CMAKE_SOURCE_DIR}/python')
|
||||
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
|
||||
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
|
||||
|
||||
|
@ -406,6 +408,7 @@ macro(GR_EXPAND_X_CC_H component root)
|
|||
|
||||
import sys, os, re
|
||||
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
|
||||
sys.path.append('${CMAKE_SOURCE_DIR}/python')
|
||||
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
|
||||
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
|
||||
|
||||
|
@ -466,6 +469,7 @@ macro(GR_EXPAND_X_CC_H_IMPL component root)
|
|||
|
||||
import sys, os, re
|
||||
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
|
||||
sys.path.append('${CMAKE_SOURCE_DIR}/python')
|
||||
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
|
||||
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright 2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
# This file was generated by gr_modtool, a tool from the GNU Radio framework
|
||||
# This file is a part of gr-ccsds
|
||||
#
|
||||
# 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
|
||||
|
@ -29,15 +30,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if(LINUX AND EXISTS "/etc/debian_version")
|
||||
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/debian_version")
|
||||
set(DEBIAN TRUE)
|
||||
endif()
|
||||
|
||||
if(LINUX AND EXISTS "/etc/redhat-release")
|
||||
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/redhat-release")
|
||||
set(REDHAT TRUE)
|
||||
endif()
|
||||
|
||||
if(LINUX AND EXISTS "/etc/slackware-version")
|
||||
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/slackware-version")
|
||||
set(SLACKWARE TRUE)
|
||||
endif()
|
||||
|
||||
|
@ -51,4 +52,12 @@ endif()
|
|||
if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
|
||||
set(LIB_SUFFIX 64)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
# Detect /lib versus /lib64
|
||||
########################################################################
|
||||
if (CMAKE_INSTALL_LIBDIR MATCHES lib64)
|
||||
set(LIB_SUFFIX 64)
|
||||
endif()
|
||||
|
||||
set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright 2010-2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
# This file was generated by gr_modtool, a tool from the GNU Radio framework
|
||||
# This file is a part of gr-ccsds
|
||||
#
|
||||
# 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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright 2010-2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
# This file was generated by gr_modtool, a tool from the GNU Radio framework
|
||||
# This file is a part of gr-ccsds
|
||||
#
|
||||
# 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
|
||||
|
@ -35,7 +36,7 @@ include(GrPython)
|
|||
function(GR_SWIG_MAKE_DOCS output_file)
|
||||
if(ENABLE_DOXYGEN)
|
||||
|
||||
#setup the input files variable list, quote formated
|
||||
#setup the input files variable list, quote formatted
|
||||
set(input_files)
|
||||
unset(INPUT_PATHS)
|
||||
foreach(input_path ${ARGN})
|
||||
|
@ -171,7 +172,12 @@ macro(GR_SWIG_MAKE name)
|
|||
#setup the actual swig library target to be built
|
||||
include(UseSWIG)
|
||||
SWIG_ADD_MODULE(${name} python ${ifiles})
|
||||
SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES})
|
||||
if(APPLE)
|
||||
set(PYTHON_LINK_OPTIONS "-undefined dynamic_lookup")
|
||||
else()
|
||||
set(PYTHON_LINK_OPTIONS ${PYTHON_LIBRARIES})
|
||||
endif(APPLE)
|
||||
SWIG_LINK_LIBRARIES(${name} ${PYTHON_LINK_OPTIONS} ${GR_SWIG_LIBRARIES})
|
||||
if(${name} STREQUAL "runtime_swig")
|
||||
SET_TARGET_PROPERTIES(${SWIG_MODULE_runtime_swig_REAL_NAME} PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
|
||||
endif(${name} STREQUAL "runtime_swig")
|
||||
|
@ -240,7 +246,7 @@ def get_swig_deps(file_path, level):
|
|||
inc_path = os.path.join(inc_dir, inc_file)
|
||||
if not os.path.exists(inc_path): continue
|
||||
deps.extend(get_swig_deps(inc_path, level-1))
|
||||
break #found, we dont search in lower prio inc dirs
|
||||
break #found, we don't search in lower prio inc dirs
|
||||
return deps
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright 2010-2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
# This file was generated by gr_modtool, a tool from the GNU Radio framework
|
||||
# This file is a part of gr-satnogs
|
||||
#
|
||||
# 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
|
||||
|
@ -45,7 +46,7 @@ function(GR_ADD_TEST test_name)
|
|||
get_target_property(location ${target} LOCATION)
|
||||
if(location)
|
||||
get_filename_component(path ${location} PATH)
|
||||
string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path})
|
||||
string(REGEX REPLACE "\\$\\(.*\\)" "${CMAKE_BUILD_TYPE}" path "${path}")
|
||||
list(APPEND GR_TEST_LIBRARY_DIRS ${path})
|
||||
endif(location)
|
||||
endforeach(target)
|
||||
|
@ -141,3 +142,35 @@ function(GR_ADD_TEST test_name)
|
|||
endif(WIN32)
|
||||
|
||||
endfunction(GR_ADD_TEST)
|
||||
|
||||
###############################################################################
|
||||
# Enables memory checking. If this function is not callled at the top-level
|
||||
# CMakeLists.txt, calls of the add_memtest() have no effect.
|
||||
###############################################################################
|
||||
function(satnogs_enable_memcheck)
|
||||
set(SATNOGS_ENABLE_MEMCHECK_VAR ON CACHE INTERNAL "SATNOGS_ENABLE_MEMCHECK")
|
||||
find_program(MEMORYCHECK_COMMAND valgrind)
|
||||
endfunction(satnogs_enable_memcheck)
|
||||
|
||||
###############################################################################
|
||||
# Adds a ctest test for memory leakage testing.
|
||||
# Params:
|
||||
# name: The name of the test
|
||||
# target: The target to be tested. Target should be a valid target created
|
||||
# from add_executable()
|
||||
###############################################################################
|
||||
function(add_memtest name target )
|
||||
if(SATNOGS_ENABLE_MEMCHECK_VAR)
|
||||
list(APPEND memcheck_cmd_options
|
||||
"--trace-children=yes;"
|
||||
"--leak-check=full;"
|
||||
"--error-exitcode=1;"
|
||||
)
|
||||
|
||||
add_test(memcheck_${name}
|
||||
${MEMORYCHECK_COMMAND}
|
||||
${memcheck_cmd_options}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${target}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
|
@ -224,9 +224,9 @@ print(re.sub('\\W', '_', '${name} ${reldir} ' + unique))"
|
|||
foreach(swig_gen_file ${${outfiles}})
|
||||
add_custom_command(
|
||||
OUTPUT ${swig_gen_file}
|
||||
COMMAND ""
|
||||
COMMAND "${CMAKE_COMMAND}" -E touch_nocreate "${swig_gen_file}"
|
||||
DEPENDS ${_target}
|
||||
COMMENT ""
|
||||
COMMENT "dummy command to show ${_target} dependency of ${swig_gen_file}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
|
|
@ -48,14 +48,14 @@ public:
|
|||
golay24 ();
|
||||
~golay24 ();
|
||||
|
||||
static const std::vector<uint32_t> G_P;
|
||||
static const std::vector<uint32_t> G_I;
|
||||
|
||||
uint32_t
|
||||
encode12(uint16_t in);
|
||||
encode12(uint16_t in, bool lsb_parity = true);
|
||||
|
||||
bool
|
||||
decode24(uint16_t *out, uint32_t in);
|
||||
private:
|
||||
std::vector<uint32_t> d_H;
|
||||
std::vector<uint32_t> d_X;
|
||||
decode24(uint32_t *out, uint32_t in);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -115,6 +115,32 @@ endif(APPLE)
|
|||
include(GrMiscUtils)
|
||||
GR_LIBRARY_FOO(gnuradio-satnogs RUNTIME_COMPONENT "satnogs_runtime" DEVEL_COMPONENT "satnogs_devel")
|
||||
|
||||
########################################################################
|
||||
# Build and register unit test
|
||||
########################################################################
|
||||
include(GrTest)
|
||||
|
||||
include_directories(${CPPUNIT_INCLUDE_DIRS})
|
||||
|
||||
list(APPEND test_satnogs_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_golay24.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_satnogs.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qa_satnogs.cc
|
||||
)
|
||||
|
||||
add_executable(test-satnogs ${test_satnogs_sources})
|
||||
|
||||
target_link_libraries(
|
||||
test-satnogs
|
||||
${GNURADIO_RUNTIME_LIBRARIES}
|
||||
${GNURADIO_BLOCKS_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${CPPUNIT_LIBRARIES}
|
||||
gnuradio-satnogs
|
||||
)
|
||||
|
||||
GR_ADD_TEST(test_satnogs test-satnogs)
|
||||
|
||||
########################################################################
|
||||
# Print summary
|
||||
########################################################################
|
||||
|
|
|
@ -70,8 +70,11 @@ namespace gr {
|
|||
pmt::pmt_t pmt_data = pmt::dict_ref(m, pmt::intern("data"), pmt::PMT_NIL);
|
||||
pmt::pmt_t pmt_erasures = pmt::dict_ref(m, pmt::intern("erasures"),
|
||||
pmt::PMT_NIL);
|
||||
/* Check if the message contains erasure info. Otherwise handle it as
|
||||
* a blob
|
||||
*/
|
||||
if (pmt::equal (pmt::PMT_NIL, pmt_data)) {
|
||||
LOG_ERROR("Invalid message format.");
|
||||
pmt_data = m;
|
||||
}
|
||||
|
||||
data_ref = pmt::u8vector_elements(pmt_data, data_len);
|
||||
|
|
|
@ -244,6 +244,7 @@ frame_acquisition_impl::searching_sync (const uint8_t* in, int len)
|
|||
d_state = DECODING_GENERIC_FRAME_LEN;
|
||||
break;
|
||||
case GOLAY24_CODED_FRAME_LEN:
|
||||
LOG_WARN("Found!");
|
||||
d_state = DECODING_GOLAY24_FRAME_LEN;
|
||||
break;
|
||||
}
|
||||
|
@ -319,6 +320,7 @@ frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len)
|
|||
{
|
||||
/* Golay24 needs 3 bytes to decode */
|
||||
const int s = std::min(len / 8, 3);
|
||||
d_frame_len = 0;
|
||||
for(int i = 0; i < s; i++) {
|
||||
uint8_t b = 0x0;
|
||||
b |= in[i * 8] << 7;
|
||||
|
@ -335,16 +337,19 @@ frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len)
|
|||
|
||||
/* Try to decode the frame length */
|
||||
if (d_cnt == 3) {
|
||||
LOG_WARN("Len coded %u", d_frame_len);
|
||||
if(d_whitening) {
|
||||
uint32_t descrambled = 0x0;
|
||||
d_whitening->descramble((uint8_t *)&descrambled,
|
||||
d_whitening->descramble((uint8_t *) &descrambled,
|
||||
(const uint8_t *)&d_frame_len, 3, false);
|
||||
d_frame_len = descrambled;
|
||||
}
|
||||
d_frame_len = ((d_frame_len & 0xFFF) << 12) | (d_frame_len >> 12);
|
||||
golay24 g = golay24 ();
|
||||
uint16_t tmp = 0;
|
||||
uint32_t tmp = 0;
|
||||
if (g.decode24 (&tmp, d_frame_len)) {
|
||||
d_frame_len = tmp;
|
||||
d_frame_len = tmp >> 12;
|
||||
LOG_WARN("Len %u", d_frame_len);
|
||||
|
||||
/* Append the CRC length if any */
|
||||
d_frame_len += d_crc_len;
|
||||
|
@ -448,7 +453,7 @@ frame_acquisition_impl::check_crc ()
|
|||
crc16_c = crc16_ibm(d_pdu, d_frame_len - 2);
|
||||
memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2);
|
||||
crc16_received = ntohs(crc16_received);
|
||||
LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c);
|
||||
LOG_WARN("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c);
|
||||
if(crc16_c == crc16_received) {
|
||||
return true;
|
||||
}
|
||||
|
|
155
lib/golay24.cc
155
lib/golay24.cc
|
@ -33,27 +33,56 @@ namespace gr
|
|||
namespace satnogs
|
||||
{
|
||||
|
||||
/*
|
||||
* Matrix P was retrieved by:
|
||||
* Lin & Costello, pg 128, Ch4, "Error Control Coding", 2nd ed, Pearson.
|
||||
*
|
||||
* Matrix mentioned by Morelos-Zaragoza, Robert H. "The art of error correcting coding."
|
||||
* John Wiley & Sons, 2006 was not suitable.
|
||||
*/
|
||||
const std::vector<uint32_t> golay24::G_P =
|
||||
{0x8ED, 0x1DB, 0x3B5, 0x769, 0xED1, 0xDA3, 0xB47, 0x68F, 0xD1D, 0xA3B, 0x477,
|
||||
0xFFE};
|
||||
|
||||
const std::vector<uint32_t> golay24::G_I =
|
||||
{ 0x800, 0x400, 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004, 0x002,
|
||||
0x001 };
|
||||
|
||||
golay24::golay24 ()
|
||||
{
|
||||
|
||||
d_H = { 0x7ff, 0xee2, 0xdc5, 0xb8b, 0xf16, 0xe2d, 0xc5b, 0x8b7, 0x96e, 0xadc,
|
||||
0xdb8, 0xb71 };
|
||||
d_X = {0x800, 0x400, 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004,
|
||||
0x002, 0x001};
|
||||
}
|
||||
|
||||
golay24::~golay24 ()
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
weight(uint32_t x)
|
||||
{
|
||||
return bit_count(x & 0xFFF);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
syndrome(uint16_t x, uint16_t y)
|
||||
{
|
||||
uint32_t s = 0;
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
s = (s << 1) | (weight(y & golay24::G_P[i]) % 2);
|
||||
}
|
||||
s ^= x;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a 12-bit message
|
||||
* @param in the input 12-bit message. The message should be placed at the
|
||||
* 12 LS bits
|
||||
* @param lsb_parity if set to true, the parity part is placed on the 12 LSB,
|
||||
* whereas if set to false it is placed on the 12 MSB of the 24 bit coded word
|
||||
* @return the coded 24-bit message. The message is placed at the 24 LS bits
|
||||
*/
|
||||
uint32_t
|
||||
golay24::encode12 (uint16_t in)
|
||||
golay24::encode12 (uint16_t in, bool lsb_parity)
|
||||
{
|
||||
uint32_t c[2] =
|
||||
{ 0x0, 0x0 };
|
||||
|
@ -61,106 +90,68 @@ golay24::encode12 (uint16_t in)
|
|||
for (size_t i = 0; i < 12; i++) {
|
||||
uint32_t tmp = 0;
|
||||
for (size_t j = 0; j < 12; j++) {
|
||||
tmp ^= (((c[0] & d_H[i]) >> j) & 0x01);
|
||||
tmp ^= (((c[0] & G_P[i]) >> j) & 0x01);
|
||||
}
|
||||
c[1] = (c[1] << 1) ^ tmp;
|
||||
}
|
||||
return ((c[0] & 0xFFF) << 12) | (c[1] & 0xFFF);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ham_dist(uint32_t x)
|
||||
{
|
||||
return bit_count(x & 0xFFF);
|
||||
if(lsb_parity) {
|
||||
return ((c[0] & 0xFFF) << 12) | (c[1] & 0xFFF);
|
||||
}
|
||||
return ((c[1] & 0xFFF) << 12) | (c[0] & 0xFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a single Golay (24, 12, 8) codeword
|
||||
*
|
||||
* @param out the 12-bit decoded message. The message is placed at the 12 LS bits
|
||||
* @param out the 24-bit decoded message. The placement of the parity is
|
||||
* implementation specific.
|
||||
*
|
||||
* @param in the coded 24 bit code word. The message should be placed at the
|
||||
* 24 LS bits
|
||||
* @return true if the decoding was successful, false in case the error correction
|
||||
* could not be performed
|
||||
*/
|
||||
bool
|
||||
golay24::decode24(uint16_t *out, const uint32_t in)
|
||||
golay24::decode24(uint32_t *out, const uint32_t in)
|
||||
{
|
||||
uint32_t e[2] = {0x0, 0x0};
|
||||
uint32_t r[2] = {0x0, 0x0};
|
||||
uint32_t c[2] = {0x0, 0x0};
|
||||
uint32_t syndrome = 0x0;
|
||||
bool found = false;
|
||||
uint32_t col = 0;
|
||||
uint32_t q = 0;
|
||||
|
||||
uint32_t s = 0x0;
|
||||
r[0] = (in >> 12) & 0xFFF;
|
||||
r[1] = in & 0xFFF;
|
||||
|
||||
for(size_t j = 0; j < 12; j++) {
|
||||
uint32_t tmp = 0x0;
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
tmp ^= (((d_X[j] & r[0]) >> i) & 0x1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
tmp ^= (((d_H[j] & r[1]) >> i) & 0x1);
|
||||
}
|
||||
syndrome = (syndrome << 1) ^ tmp;
|
||||
s = syndrome(r[0], r[1]);
|
||||
if(weight(s) <= 3) {
|
||||
*out = ((r[0] ^ s) << 12) | (r[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(ham_dist(syndrome) <= 3) {
|
||||
e[0] = syndrome;
|
||||
e[1] = 0x0;
|
||||
}
|
||||
else{
|
||||
do {
|
||||
if (ham_dist (syndrome ^ d_H[col]) <= 2) {
|
||||
e[0] = syndrome ^ d_H[col];
|
||||
e[1] = d_X[col];
|
||||
found = 1;
|
||||
}
|
||||
col++;
|
||||
}
|
||||
while ((col < 12) && !found);
|
||||
|
||||
if ((col == 12) && !found) {
|
||||
for (size_t j = 0; j < 12; j++) {
|
||||
uint32_t tmp = 0x0;
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
tmp ^= (((d_H[j] & syndrome) >> i) & 0x1);
|
||||
}
|
||||
q = (q << 1) ^ tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (ham_dist (q) <= 3) {
|
||||
e[0] = 0;
|
||||
e[1] = q;
|
||||
}
|
||||
else {
|
||||
col = 0;
|
||||
found = 0;
|
||||
do {
|
||||
if (ham_dist (q ^ d_H[col]) <= 2) {
|
||||
e[0] = d_X[col];
|
||||
e[1] = q ^ d_H[col];
|
||||
found = 1;
|
||||
}
|
||||
col++;
|
||||
}
|
||||
while ((col < 12) && !found);
|
||||
|
||||
if (col == 12 && !found) {
|
||||
return false;
|
||||
}
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
const uint16_t tmp = s ^ G_P[i];
|
||||
if(weight(tmp) <= 2) {
|
||||
*out = ((r[0] ^ tmp) << 12) | (r[1] ^ G_I[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
c[0] = r[0] ^ e[0];
|
||||
c[1] = r[1] ^ e[1];
|
||||
/* Return the message part only, not the parity */
|
||||
*out = c[0];
|
||||
return true;
|
||||
|
||||
/* Compute the sP vector */
|
||||
uint32_t sP = 0;
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
sP = (sP << 1) | (weight(s & G_P[i]) % 2);
|
||||
}
|
||||
if(weight(sP) == 2 || weight(sP) == 3) {
|
||||
*out = (r[0] << 12) | (r[1] ^ sP);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 12; i++) {
|
||||
const uint16_t tmp = sP ^ G_P[i];
|
||||
if(weight(tmp) == 2) {
|
||||
*out = ((r[0] ^ G_I[i]) << 12) | (r[1] ^ tmp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qa_golay24.h"
|
||||
#include <satnogs/golay24.h>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
namespace gr {
|
||||
|
||||
namespace satnogs {
|
||||
|
||||
/* Inspired by the example 4.7 of
|
||||
* Lin & Costello, Ch4, "Error Control Coding", 2nd ed, Pearson.
|
||||
*/
|
||||
void
|
||||
qa_golay24::example_47()
|
||||
{
|
||||
golay24 gol;
|
||||
uint32_t r = 0b100000110100110000000001;
|
||||
uint32_t res;
|
||||
bool ret = gol.decode24 (&res, r);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res >> 12) == 0b100100110110);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qa_golay24::errors_0()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<uint16_t> uni(0, 0xFFFF);
|
||||
|
||||
uint16_t x = uni(mt) & 0xFFF;
|
||||
golay24 gol;
|
||||
uint32_t coded = gol.encode12(x);
|
||||
|
||||
uint32_t res;
|
||||
bool ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res >> 12) == x);
|
||||
|
||||
coded = gol.encode12(x, false);
|
||||
ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res & 0xFFF) == x);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
flip(uint32_t in, uint32_t n)
|
||||
{
|
||||
if(!n || n > 24) {
|
||||
return in;
|
||||
}
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<uint8_t> flip(0, 23);
|
||||
std::vector<uint8_t> idx;
|
||||
while(idx.size() < n) {
|
||||
uint8_t i = flip(mt);
|
||||
if (std::find(idx.begin(), idx.end(), i) == idx.end()) {
|
||||
idx.push_back(i);
|
||||
}
|
||||
}
|
||||
uint32_t mask = 0;
|
||||
for(uint8_t i : idx) {
|
||||
mask |= (1 << i);
|
||||
}
|
||||
return in ^ mask;
|
||||
}
|
||||
|
||||
void
|
||||
qa_golay24::errors_1()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<uint16_t> uni(0, 0xFFFF);
|
||||
|
||||
for(size_t i = 0; i < 2048; i++) {
|
||||
uint16_t x = uni(mt) & 0xFFF;
|
||||
golay24 gol;
|
||||
uint32_t coded = gol.encode12(x);
|
||||
/* Apply bit flip */
|
||||
uint32_t coder_error = flip(coded, 1);
|
||||
|
||||
uint32_t res;
|
||||
bool ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res >> 12)== x);
|
||||
|
||||
coded = gol.encode12(x, false);
|
||||
/* Apply bit flip */
|
||||
coder_error = flip(coded, 1);
|
||||
ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res & 0xFFF)== x);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qa_golay24::errors_3()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<uint16_t> uni(0, 0xFFFF);
|
||||
|
||||
for(size_t i = 0; i < 2048; i++) {
|
||||
uint16_t x = uni(mt) & 0xFFF;
|
||||
golay24 gol;
|
||||
uint32_t coded = gol.encode12(x);
|
||||
/* Apply bit flip */
|
||||
uint32_t coder_error = flip(coded, 3);
|
||||
|
||||
uint32_t res;
|
||||
bool ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res >> 12)== x);
|
||||
|
||||
coded = gol.encode12(x, false);
|
||||
/* Apply bit flip */
|
||||
coder_error = flip(coded, 3);
|
||||
ret = gol.decode24(&res, coded);
|
||||
CPPUNIT_ASSERT(ret);
|
||||
CPPUNIT_ASSERT((res & 0xFFF)== x);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qa_golay24::errors_4()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<uint16_t> uni(0, 0xFFFF);
|
||||
|
||||
for(size_t i = 0; i < 2048; i++) {
|
||||
uint16_t x = uni(mt) & 0xFFF;
|
||||
golay24 gol;
|
||||
uint32_t coded = gol.encode12(x);
|
||||
/* Apply bit flip */
|
||||
uint32_t coder_error = flip(coded, 4);
|
||||
|
||||
uint32_t res;
|
||||
bool ret = gol.decode24(&res, coded);
|
||||
if(ret) {
|
||||
CPPUNIT_ASSERT((res >> 12)== x);
|
||||
}
|
||||
|
||||
coded = gol.encode12(x, false);
|
||||
/* Apply bit flip */
|
||||
coder_error = flip(coded, 4);
|
||||
ret = gol.decode24(&res, coded);
|
||||
if(ret) {
|
||||
CPPUNIT_ASSERT((res & 0xFFF)== x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace satnogs
|
||||
|
||||
} // namespace gr
|
|
@ -0,0 +1,66 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIB_QA_GOLAY24_H_
|
||||
#define LIB_QA_GOLAY24_H_
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
#include <satnogs/golay24.h>
|
||||
|
||||
namespace gr {
|
||||
|
||||
namespace satnogs {
|
||||
|
||||
class qa_golay24 : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
CPPUNIT_TEST_SUITE(qa_golay24);
|
||||
CPPUNIT_TEST(example_47);
|
||||
CPPUNIT_TEST(errors_0);
|
||||
CPPUNIT_TEST(errors_1);
|
||||
CPPUNIT_TEST(errors_3);
|
||||
CPPUNIT_TEST(errors_4);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void
|
||||
example_47();
|
||||
|
||||
void
|
||||
errors_0 ();
|
||||
|
||||
void
|
||||
errors_1 ();
|
||||
|
||||
void
|
||||
errors_3 ();
|
||||
|
||||
void
|
||||
errors_4 ();
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
||||
} // namespace gr
|
||||
|
||||
|
||||
|
||||
#endif /* LIB_QA_GOLAY24_H_ */
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qa_satnogs.h"
|
||||
#include "qa_golay24.h"
|
||||
|
||||
CppUnit::TestSuite *
|
||||
qa_satnogs::suite()
|
||||
{
|
||||
CppUnit::TestSuite *s = new CppUnit::TestSuite("satnogs");
|
||||
s->addTest(gr::satnogs::qa_golay24::suite());
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QA_SATNOGS_H_
|
||||
#define _QA_SATNOGS_H_
|
||||
|
||||
#include <gnuradio/attributes.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
|
||||
class __GR_ATTR_EXPORT qa_satnogs
|
||||
{
|
||||
public:
|
||||
|
||||
static CppUnit::TestSuite *suite();
|
||||
};
|
||||
|
||||
#endif /* _QA_SATNOGS_H_ */
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cppunit/TextTestRunner.h>
|
||||
#include <cppunit/XmlOutputter.h>
|
||||
#include <cppunit/BriefTestProgressListener.h>
|
||||
#include <cppunit/TestResultCollector.h>
|
||||
#include <cppunit/TestResult.h>
|
||||
|
||||
#include <gnuradio/unittests.h>
|
||||
#include "qa_satnogs.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
CppUnit::TestResultCollector result;
|
||||
CppUnit::BriefTestProgressListener progressListener;
|
||||
CppUnit::TextTestRunner runner;
|
||||
|
||||
runner.addTest(qa_satnogs::suite());
|
||||
runner.eventManager().addListener(&result);
|
||||
runner.eventManager().addListener(&progressListener);
|
||||
|
||||
bool was_successful = runner.run("", false);
|
||||
|
||||
return was_successful ? 0 : 1;
|
||||
}
|
Loading…
Reference in New Issue