kopia lustrzana https://github.com/mobilinkd/m17-cxx-demod
Merge pull request #18 from robojay/master
Modifications for conda-forge and local conda (Windows) buildingpull/23/head
commit
7e30f0601a
|
@ -5,7 +5,7 @@ project(m17cxx
|
|||
DESCRIPTION "M17 Digital Voice modulation and demodulation"
|
||||
LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
# Require out-of-source builds
|
||||
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
|
||||
|
@ -24,10 +24,9 @@ message(STATUS "# Checking dependencies")
|
|||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
include(FindPkgConfig)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
pkg_check_modules(CODEC2 REQUIRED codec2)
|
||||
find_package(codec2 REQUIRED)
|
||||
set(Boost_USE_STATIC_LIBS FALSE)
|
||||
find_package(Boost COMPONENTS program_options REQUIRED)
|
||||
|
||||
|
|
14
README.md
14
README.md
|
@ -31,6 +31,20 @@ It also requires a modern C++17 compiler (GCC 8 minimum).
|
|||
make test
|
||||
sudo make install
|
||||
|
||||
## Build Steps for local building under Anaconda for Windows
|
||||
|
||||
### Prequisites
|
||||
- Microsoft Visual Studio 2019
|
||||
- Miniconda (or Anaconda) x64 for Windows
|
||||
|
||||
### From a clean Conda environment
|
||||
|
||||
conda config --add channels conda-forge
|
||||
conda create -n M17 vs2019_win-64 cmake ninja pkg-config boost-cpp gtest gmock gtest libcodec2
|
||||
conda activate M17
|
||||
|
||||
### And then from the top level of the m17-cxx-demod repo, execute win_build.bat
|
||||
|
||||
## Running
|
||||
|
||||
This program was designed to be used with RTL-SDR, specifically rtl-fm.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
add_executable(m17-demod m17-demod.cpp)
|
||||
target_link_libraries(m17-demod PRIVATE m17cxx ${CODEC2_LIBRARIES} ${Boost_LIBRARIES})
|
||||
target_link_libraries(m17-demod PRIVATE m17cxx codec2 Boost::program_options)
|
||||
|
||||
add_executable(m17-mod m17-mod.cpp)
|
||||
target_link_libraries(m17-mod PRIVATE m17cxx ${CODEC2_LIBRARIES} ${Boost_LIBRARIES} Threads::Threads)
|
||||
target_link_libraries(m17-mod PRIVATE m17cxx codec2 Boost::program_options Threads::Threads)
|
||||
|
||||
install(TARGETS m17-demod m17-mod RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -190,15 +190,15 @@ bool demodulate_audio(mobilinkd::M17FrameDecoder::audio_buffer_t const& audio, i
|
|||
if (noise_blanker && viterbi_cost > 80)
|
||||
{
|
||||
buf.fill(0);
|
||||
std::cout.write((const char*)buf.begin(), 320);
|
||||
std::cout.write((const char*)buf.begin(), 320);
|
||||
std::cout.write((const char*)buf.data(), 320);
|
||||
std::cout.write((const char*)buf.data(), 320);
|
||||
}
|
||||
else
|
||||
{
|
||||
codec2_decode(codec2, buf.begin(), audio.begin() + 2);
|
||||
std::cout.write((const char*)buf.begin(), 320);
|
||||
codec2_decode(codec2, buf.begin(), audio.begin() + 10);
|
||||
std::cout.write((const char*)buf.begin(), 320);
|
||||
codec2_decode(codec2, buf.data(), audio.data() + 2);
|
||||
std::cout.write((const char*)buf.data(), 320);
|
||||
codec2_decode(codec2, buf.data(), audio.data() + 10);
|
||||
std::cout.write((const char*)buf.data(), 320);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -104,11 +104,11 @@ class ClockRecovery
|
|||
int8_t offset = sample_index_ - prev_sample_index_;
|
||||
|
||||
// When in spec, the clock should drift by less than 1 sample per frame.
|
||||
if (__builtin_expect(offset >= MAX_OFFSET, 0))
|
||||
if (offset >= MAX_OFFSET) [[unlikely]]
|
||||
{
|
||||
offset -= SAMPLES_PER_SYMBOL;
|
||||
}
|
||||
else if (__builtin_expect(offset <= -MAX_OFFSET, 0))
|
||||
else if (offset <= -MAX_OFFSET) [[unlikely]]
|
||||
{
|
||||
offset += SAMPLES_PER_SYMBOL;
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class ClockRecovery
|
|||
{
|
||||
// update_sample_index_() must be called first.
|
||||
|
||||
if (__builtin_expect((frame_count_ == 0), 0))
|
||||
if (frame_count_ == 0) [[unlikely]]
|
||||
{
|
||||
prev_sample_index_ = sample_index_;
|
||||
offset_ = 0.0;
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# define __builtin_popcount __popcnt
|
||||
#endif
|
||||
|
||||
namespace mobilinkd
|
||||
{
|
||||
|
||||
inline constexpr uint32_t convolve_bit(uint32_t poly, uint32_t memory)
|
||||
{
|
||||
return __builtin_popcount(poly & memory) & 1;
|
||||
return std::popcount(poly & memory) & 1;
|
||||
}
|
||||
|
||||
template <size_t K, size_t k = 1>
|
||||
|
|
|
@ -4,15 +4,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# define __builtin_popcount __popcnt
|
||||
#endif
|
||||
|
||||
namespace mobilinkd {
|
||||
|
||||
// Parts are adapted from:
|
||||
|
@ -90,11 +86,13 @@ constexpr array<T, N> sort(array<T, N> array)
|
|||
// static constexpr uint16_t POLY = 0xAE3;
|
||||
constexpr uint16_t POLY = 0xC75;
|
||||
|
||||
struct __attribute__((packed)) SyndromeMapEntry
|
||||
#pragma pack(push, 1)
|
||||
struct SyndromeMapEntry
|
||||
{
|
||||
uint32_t a{0};
|
||||
uint16_t b{0};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* Calculate the syndrome of a [23,12] Golay codeword.
|
||||
|
@ -115,7 +113,7 @@ constexpr uint32_t syndrome(uint32_t codeword)
|
|||
|
||||
constexpr bool parity(uint32_t codeword)
|
||||
{
|
||||
return __builtin_popcount(codeword) & 1;
|
||||
return std::popcount(codeword) & 1;
|
||||
}
|
||||
|
||||
constexpr SyndromeMapEntry makeSyndromeMapEntry(uint64_t val)
|
||||
|
@ -217,7 +215,7 @@ bool decode(uint32_t input, uint32_t& output)
|
|||
// Apply the correction to the input.
|
||||
output = input ^ correction;
|
||||
// Only test parity for 3-bit errors.
|
||||
return __builtin_popcount(syndrm) < 3 || !parity(output);
|
||||
return std::popcount(syndrm) < 3 || !parity(output);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -556,7 +556,7 @@ void M17Demodulator<FloatType>::operator()(const FloatType input)
|
|||
|
||||
// We need to pump a few ms of data through on startup to initialize
|
||||
// the demodulator.
|
||||
if (__builtin_expect((initializing), 0))
|
||||
if (initializing) [[unlikely]]
|
||||
{
|
||||
--initializing;
|
||||
initialize(input);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct M17Framer
|
|||
if (index_ == N)
|
||||
{
|
||||
index_ = 0;
|
||||
*result = buffer_.begin();
|
||||
*result = buffer_.data();
|
||||
return N;
|
||||
}
|
||||
return 0;
|
||||
|
@ -46,7 +46,7 @@ struct M17Framer
|
|||
if (index_ == N)
|
||||
{
|
||||
index_ = 0;
|
||||
*result = buffer_.begin();
|
||||
*result = buffer_.data();
|
||||
return N;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -2,13 +2,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# define __builtin_popcount __popcnt
|
||||
#endif
|
||||
|
||||
namespace mobilinkd
|
||||
{
|
||||
|
||||
|
@ -29,7 +25,7 @@ struct M17Synchronizer
|
|||
|
||||
buffer_ = ((buffer_ << 2) | bits) & 0xFFFF;
|
||||
auto tmp = buffer_ ^ expected_;
|
||||
return __builtin_popcount(tmp) <= allowable_errors_;
|
||||
return std::popcount(tmp) <= allowable_errors_;
|
||||
}
|
||||
|
||||
void reset() { buffer_ = 0; }
|
||||
|
|
|
@ -5,7 +5,13 @@ target_include_directories(m17cxx INTERFACE
|
|||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
target_compile_features(m17cxx INTERFACE cxx_std_17)
|
||||
target_compile_features(m17cxx INTERFACE cxx_std_20)
|
||||
|
||||
if(MSVC)
|
||||
# specify standards-conformance mode
|
||||
target_compile_options(m17cxx INTERFACE /permissive-)
|
||||
target_compile_definitions(m17cxx INTERFACE _USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
source_group(
|
||||
TREE "${PROJECT_SOURCE_DIR}/include"
|
||||
|
|
|
@ -1,71 +1,76 @@
|
|||
include(GoogleTest)
|
||||
pkg_check_modules(CODEC2 REQUIRED codec2)
|
||||
|
||||
include_directories (
|
||||
${TEST_SOURCE_DIR}
|
||||
..
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PTHREAD "")
|
||||
else()
|
||||
set(PTHREAD "pthread")
|
||||
endif(WIN32)
|
||||
|
||||
add_executable (ConvolutionTest ConvolutionTest.cpp)
|
||||
target_link_libraries(ConvolutionTest m17cxx gtest pthread)
|
||||
target_link_libraries(ConvolutionTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(ConvolutionTest "" AUTO)
|
||||
|
||||
add_executable (M17FramerTest M17FramerTest.cpp)
|
||||
target_link_libraries(M17FramerTest m17cxx gtest pthread)
|
||||
target_link_libraries(M17FramerTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(M17FramerTest "" AUTO)
|
||||
|
||||
add_executable (TrellisTest TrellisTest.cpp)
|
||||
target_link_libraries(TrellisTest m17cxx gtest pthread)
|
||||
target_link_libraries(TrellisTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(TrellisTest "" AUTO)
|
||||
|
||||
add_executable (ViterbiTest ViterbiTest.cpp)
|
||||
target_link_libraries(ViterbiTest m17cxx gtest pthread)
|
||||
target_link_libraries(ViterbiTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(ViterbiTest "" AUTO)
|
||||
|
||||
add_executable (Golay24Test Golay24Test.cpp)
|
||||
target_link_libraries(Golay24Test m17cxx gtest pthread)
|
||||
target_link_libraries(Golay24Test m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(Golay24Test "" AUTO)
|
||||
|
||||
add_executable (CRC16Test CRC16Test.cpp)
|
||||
target_link_libraries(CRC16Test m17cxx gtest pthread)
|
||||
target_link_libraries(CRC16Test m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(CRC16Test "" AUTO)
|
||||
|
||||
add_executable (M17RandomizerTest M17RandomizerTest.cpp)
|
||||
target_link_libraries(M17RandomizerTest m17cxx gtest pthread)
|
||||
target_link_libraries(M17RandomizerTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(M17RandomizerTest "" AUTO)
|
||||
|
||||
add_executable (PolynomialInterleaverTest PolynomialInterleaverTest.cpp)
|
||||
target_link_libraries(PolynomialInterleaverTest m17cxx gtest pthread)
|
||||
target_link_libraries(PolynomialInterleaverTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(PolynomialInterleaverTest "" AUTO)
|
||||
|
||||
add_executable (M17ModulatorTest M17ModulatorTest.cpp)
|
||||
target_link_libraries(M17ModulatorTest m17cxx gtest pthread codec2)
|
||||
target_link_libraries(M17ModulatorTest m17cxx GTest::GTest ${PTHREAD} codec2)
|
||||
gtest_add_tests(M17ModulatorTest "" AUTO)
|
||||
|
||||
add_executable (UtilTest UtilTest.cpp)
|
||||
target_link_libraries(UtilTest m17cxx gtest pthread)
|
||||
target_link_libraries(UtilTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(UtilTest "" AUTO)
|
||||
|
||||
add_executable (LinkSetupFrameTest LinkSetupFrameTest.cpp)
|
||||
target_link_libraries(LinkSetupFrameTest m17cxx gtest pthread)
|
||||
target_link_libraries(LinkSetupFrameTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(LinkSetupFrameTest "" AUTO)
|
||||
|
||||
add_executable (SlidingDFTTest SlidingDFTTest.cpp)
|
||||
target_link_libraries(SlidingDFTTest m17cxx gtest pthread)
|
||||
target_link_libraries(SlidingDFTTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(SlidingDFTTest "" AUTO)
|
||||
|
||||
add_executable (DataCarrierDetectTest DataCarrierDetectTest.cpp)
|
||||
target_link_libraries(DataCarrierDetectTest m17cxx gtest pthread)
|
||||
target_link_libraries(DataCarrierDetectTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(DataCarrierDetectTest "" AUTO)
|
||||
|
||||
add_executable (ClockRecoveryTest ClockRecoveryTest.cpp)
|
||||
target_link_libraries(ClockRecoveryTest m17cxx gtest pthread)
|
||||
target_link_libraries(ClockRecoveryTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(ClockRecoveryTest "" AUTO)
|
||||
|
||||
add_executable (FreqDevEstimatorTest FreqDevEstimatorTest.cpp)
|
||||
target_link_libraries(FreqDevEstimatorTest m17cxx gtest pthread)
|
||||
target_link_libraries(FreqDevEstimatorTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(FreqDevEstimatorTest "" AUTO)
|
||||
|
||||
add_executable (CorrelatorTest CorrelatorTest.cpp)
|
||||
target_link_libraries(CorrelatorTest m17cxx gtest pthread)
|
||||
target_link_libraries(CorrelatorTest m17cxx GTest::GTest ${PTHREAD})
|
||||
gtest_add_tests(CorrelatorTest "" AUTO)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -210,7 +211,7 @@ TEST_F(UtilTest, PRBS9)
|
|||
uint16_t lfsr = 0x100;
|
||||
|
||||
for (size_t i = 0; i != 511; ++i) {
|
||||
lfsr = ((__builtin_popcount(lfsr & 0x11) & 1) << 8) | (lfsr >> 1);
|
||||
lfsr = ((std::popcount(lfsr & 0x11u) & 1) << 8) | (lfsr >> 1);
|
||||
bool p = (lfsr & 0x100) == 0x100;
|
||||
bool n = prbs.generate();
|
||||
EXPECT_EQ(p,n) << "i = " << i;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
::
|
||||
:: win_build.bat
|
||||
::
|
||||
:: Batch file to locally build under Windows using Conda
|
||||
::
|
||||
:: See README.md for details
|
||||
::
|
||||
setlocal EnableDelayedExpansion
|
||||
@echo on
|
||||
|
||||
:: Set number of CPUs to use for build
|
||||
set CPU_COUNT=3
|
||||
|
||||
:: Make a build folder and change to it
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
:: configure
|
||||
cmake -G "Ninja" ^
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="%LIBRARY_PREFIX%" ^
|
||||
-DCMAKE_PREFIX_PATH:PATH="%LIBRARY_PREFIX%" ^
|
||||
..
|
||||
if errorlevel 1 exit /B 1
|
||||
|
||||
:: build
|
||||
cmake --build . --config Release -- -j%CPU_COUNT%
|
||||
if errorlevel 1 exit /B 1
|
||||
|
||||
:: install
|
||||
cmake --build . --config Release --target install
|
||||
if errorlevel 1 exit /B 1
|
||||
|
||||
:: test
|
||||
ctest --build-config Release --output-on-failure --timeout 120 -j%CPU_COUNT%
|
||||
if errorlevel 1 exit /B 1
|
Ładowanie…
Reference in New Issue