mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2026-04-20 23:22:43 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15112c63b7 | ||
|
|
115cb23672 | ||
|
|
101f6777ee | ||
|
|
82a2a4c04a | ||
|
|
c4086f5719 | ||
|
|
5f77718d75 | ||
|
|
e613087e97 | ||
|
|
beb18972ea | ||
|
|
1b0a5ed88e | ||
|
|
b1ad7590cc | ||
|
|
9537ccf2d2 | ||
|
|
0ac1bd56bc | ||
|
|
936c99dc40 |
303
.github/workflows/build_all.yml
vendored
303
.github/workflows/build_all.yml
vendored
@@ -36,13 +36,6 @@ jobs:
|
|||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/" ; rm "C:/Program Files/PothosSDR/lib/libusb-1.0.lib" ; cp "libusb_old/MS64/dll/libusb-1.0.lib" "C:/Program Files/PothosSDR/lib/"
|
run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/" ; rm "C:/Program Files/PothosSDR/lib/libusb-1.0.lib" ; cp "libusb_old/MS64/dll/libusb-1.0.lib" "C:/Program Files/PothosSDR/lib/"
|
||||||
|
|
||||||
- name: Download librtlsdr
|
|
||||||
run: Invoke-WebRequest -Uri "https://ftp.osmocom.org/binaries/windows/rtl-sdr/rtl-sdr-64bit-20240623.zip" -OutFile ${{runner.workspace}}/rtl-sdr.zip
|
|
||||||
|
|
||||||
- name: Patch Pothos with newer librtlsdr version
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: 7z x rtl-sdr.zip ; rm "C:/Program Files/PothosSDR/bin/rtlsdr.dll" ; cp "rtl-sdr-64bit-20240623/librtlsdr.dll" "C:/Program Files/PothosSDR/bin/rtlsdr.dll"
|
|
||||||
|
|
||||||
- name: Download SDRPlay API
|
- name: Download SDRPlay API
|
||||||
run: Invoke-WebRequest -Uri "https://www.sdrpp.org/SDRplay.zip" -OutFile ${{runner.workspace}}/SDRplay.zip
|
run: Invoke-WebRequest -Uri "https://www.sdrpp.org/SDRplay.zip" -OutFile ${{runner.workspace}}/SDRplay.zip
|
||||||
|
|
||||||
@@ -50,7 +43,7 @@ jobs:
|
|||||||
run: 7z x ${{runner.workspace}}/SDRplay.zip -o"C:/Program Files/"
|
run: 7z x ${{runner.workspace}}/SDRplay.zip -o"C:/Program Files/"
|
||||||
|
|
||||||
- name: Download codec2
|
- name: Download codec2
|
||||||
run: git clone https://github.com/drowe67/codec2
|
run: git clone https://github.com/AlexandreRouma/codec2
|
||||||
|
|
||||||
- name: Prepare MinGW
|
- name: Prepare MinGW
|
||||||
run: C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -c "pacman --noconfirm -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja"
|
run: C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -c "pacman --noconfirm -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja"
|
||||||
@@ -65,30 +58,25 @@ jobs:
|
|||||||
run: mkdir "C:/Program Files/codec2" ; mkdir "C:/Program Files/codec2/include" ; mkdir "C:/Program Files/codec2/include/codec2" ; mkdir "C:/Program Files/codec2/lib" ; cd "codec2" ; xcopy "src" "C:/Program Files/codec2/include" ; cd "build" ; xcopy "src" "C:/Program Files/codec2/lib" ; xcopy "codec2" "C:/Program Files/codec2/include/codec2"
|
run: mkdir "C:/Program Files/codec2" ; mkdir "C:/Program Files/codec2/include" ; mkdir "C:/Program Files/codec2/include/codec2" ; mkdir "C:/Program Files/codec2/lib" ; cd "codec2" ; xcopy "src" "C:/Program Files/codec2/include" ; cd "build" ; xcopy "src" "C:/Program Files/codec2/lib" ; xcopy "codec2" "C:/Program Files/codec2/include/codec2"
|
||||||
|
|
||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
run: vcpkg install fftw3:x64-windows glfw3:x64-windows portaudio:x64-windows zstd:x64-windows libusb:x64-windows spdlog:x64-windows
|
run: vcpkg install fftw3:x64-windows glfw3:x64-windows portaudio:x64-windows zstd:x64-windows libusb:x64-windows
|
||||||
|
|
||||||
- name: Install rtaudio
|
- name: Install rtaudio
|
||||||
run: git clone https://github.com/thestk/rtaudio ; cd rtaudio ; git checkout 2f2fca4502d506abc50f6d4473b2836d24cfb1e3 ; mkdir build ; cd build ; cmake .. ; cmake --build . --config Release ; cmake --install .
|
run: git clone https://github.com/thestk/rtaudio ; cd rtaudio ; git checkout 2f2fca4502d506abc50f6d4473b2836d24cfb1e3 ; mkdir build ; cd build ; cmake .. ; cmake --build . --config Release ; cmake --install .
|
||||||
|
|
||||||
- name: Install libperseus-sdr
|
- name: Install libperseus-sdr
|
||||||
run: git clone https://github.com/AlexandreRouma/libperseus-sdr ; cd libperseus-sdr ; mkdir build ; cd build ; cmake -DCMAKE_BUILD_TYPE=Release "-DLIBUSB_LIBRARIES=C:/Program Files/PothosSDR/lib/libusb-1.0.lib" "-DLIBUSB_INCLUDE_DIRS=C:/Program Files/PothosSDR/include/libusb-1.0" .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; mkdir "C:/Program Files/PothosSDR/include/perseus-sdr" ; cp Release/perseus-sdr.dll "C:/Program Files/PothosSDR/bin" ; cp Release/perseus-sdr.lib "C:/Program Files/PothosSDR/bin" ; cd .. ; xcopy "src" "C:/Program Files/PothosSDR/include/perseus-sdr"
|
run: git clone https://github.com/AlexandreRouma/libperseus-sdr ; cd libperseus-sdr ; mkdir build ; cd build ; cmake "-DLIBUSB_LIBRARIES=C:/Program Files/PothosSDR/lib/libusb-1.0.lib" "-DLIBUSB_INCLUDE_DIRS=C:/Program Files/PothosSDR/include/libusb-1.0" .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; mkdir "C:/Program Files/PothosSDR/include/perseus-sdr" ; cp Release/perseus-sdr.dll "C:/Program Files/PothosSDR/bin" ; cp Release/perseus-sdr.lib "C:/Program Files/PothosSDR/bin" ; cd .. ; xcopy "src" "C:/Program Files/PothosSDR/include/perseus-sdr"
|
||||||
|
|
||||||
- name: Install librfnm
|
|
||||||
run: git clone https://github.com/AlexandreRouma/librfnm ; cd librfnm ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; cmake --install .
|
|
||||||
|
|
||||||
- name: Install libfobos
|
|
||||||
run: git clone https://github.com/AlexandreRouma/libfobos ; cd libfobos ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; cmake --install .
|
|
||||||
|
|
||||||
- name: Install libhydrasdr
|
|
||||||
run: git clone https://github.com/hydrasdr/rfone_host; cd rfone_host/ ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Release "-DLIBUSB_LIBRARIES=C:\Program Files\PothosSDR\lib\libusb-1.0.lib" "-DLIBUSB_INCLUDE_DIR=C:\Program Files\PothosSDR\include\libusb-1.0" "-DTHREADS_PTHREADS_WIN32_LIBRARY=C:\Program Files\PothosSDR\lib\pthreadVC2.lib" "-DTHREADS_PTHREADS_INCLUDE_DIR=C:\Program Files\PothosSDR\include" ; cmake --build . --config Release ; cmake --install .
|
|
||||||
|
|
||||||
- name: Prepare CMake
|
- name: Prepare CMake
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
run: cmake -DCOPY_MSVC_REDISTRIBUTABLES=ON "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON
|
run: cmake "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DCMAKE_BUILD_TYPE=Debug -DCOPY_MSVC_REDISTRIBUTABLES=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
run: cmake --build . --config Release --verbose
|
run: cmake --build . --config Debug --verbose
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
run: ./Debug/min_broken.exe
|
||||||
|
|
||||||
- name: Create Archive
|
- name: Create Archive
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
@@ -101,7 +89,7 @@ jobs:
|
|||||||
path: ${{runner.workspace}}/sdrpp_windows_x64.zip
|
path: ${{runner.workspace}}/sdrpp_windows_x64.zip
|
||||||
|
|
||||||
build_macos_intel:
|
build_macos_intel:
|
||||||
runs-on: macos-15-intel
|
runs-on: macos-12
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -110,7 +98,7 @@ jobs:
|
|||||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool spdlog && pip3 install mako --break-system-packages
|
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool && pip3 install mako
|
||||||
|
|
||||||
- name: Install volk
|
- name: Install volk
|
||||||
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
@@ -122,32 +110,20 @@ jobs:
|
|||||||
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install libad9361
|
- name: Install libad9361
|
||||||
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 .. && make -j3 && sudo make install && cd ../../
|
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install LimeSuite
|
- name: Install LimeSuite
|
||||||
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install libperseus
|
- name: Install libperseus
|
||||||
run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && sudo make install && cd ..
|
run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
|
||||||
|
|
||||||
- name: Install librfnm
|
|
||||||
run: git clone https://github.com/AlexandreRouma/librfnm && cd librfnm && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
|
|
||||||
|
|
||||||
- name: Install libfobos
|
|
||||||
run: git clone https://github.com/AlexandreRouma/libfobos && cd libfobos && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
|
|
||||||
|
|
||||||
- name: Install more recent librtlsdr
|
- name: Install more recent librtlsdr
|
||||||
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
|
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install libhydrasdr
|
|
||||||
run: git clone https://github.com/hydrasdr/rfone_host && cd rfone_host && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
|
||||||
|
|
||||||
- name: Install libdlcr
|
|
||||||
run: wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip && mkdir dlcr_host && cd dlcr_host && 7z x ../dlcr_host_v0.3.0.zip && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 .. -DCMAKE_BUILD_TYPE=Release && make -j2 && sudo make install && cd ../../
|
|
||||||
|
|
||||||
- name: Prepare CMake
|
- name: Prepare CMake
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
run: cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
|
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
@@ -164,7 +140,7 @@ jobs:
|
|||||||
path: ${{runner.workspace}}/sdrpp_macos_intel.zip
|
path: ${{runner.workspace}}/sdrpp_macos_intel.zip
|
||||||
|
|
||||||
build_macos_arm:
|
build_macos_arm:
|
||||||
runs-on: macos-15
|
runs-on: macos-14
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -173,7 +149,7 @@ jobs:
|
|||||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool spdlog && pip3 install mako --break-system-packages
|
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool && pip3 install mako --break-system-packages
|
||||||
|
|
||||||
- name: Install volk
|
- name: Install volk
|
||||||
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
@@ -185,7 +161,7 @@ jobs:
|
|||||||
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install libad9361
|
- name: Install libad9361
|
||||||
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 .. && make -j3 && sudo make install && cd ../../
|
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install LimeSuite
|
- name: Install LimeSuite
|
||||||
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
||||||
@@ -193,24 +169,12 @@ jobs:
|
|||||||
# - name: Install libperseus
|
# - name: Install libperseus
|
||||||
# run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
|
# run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
|
||||||
|
|
||||||
- name: Install librfnm
|
|
||||||
run: git clone https://github.com/AlexandreRouma/librfnm && cd librfnm && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
|
|
||||||
|
|
||||||
- name: Install libfobos
|
|
||||||
run: git clone https://github.com/AlexandreRouma/libfobos && cd libfobos && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
|
|
||||||
|
|
||||||
- name: Install more recent librtlsdr
|
- name: Install more recent librtlsdr
|
||||||
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
|
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
|
||||||
|
|
||||||
- name: Install libhydrasdr
|
|
||||||
run: git clone https://github.com/hydrasdr/rfone_host && cd rfone_host && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
|
|
||||||
|
|
||||||
- name: Install libdlcr
|
|
||||||
run: wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip && mkdir dlcr_host && cd dlcr_host && 7z x ../dlcr_host_v0.3.0.zip && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 .. -DCMAKE_BUILD_TYPE=Release && make -j2 && sudo make install && cd ../../
|
|
||||||
|
|
||||||
- name: Prepare CMake
|
- name: Prepare CMake
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
run: cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF -DOPT_BUILD_PERSEUS_SOURCE=OFF -DOPT_BUILD_AUDIO_SOURCE=OFF -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
|
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF -DOPT_BUILD_PERSEUS_SOURCE=OFF -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
@@ -226,7 +190,29 @@ jobs:
|
|||||||
name: sdrpp_macos_arm
|
name: sdrpp_macos_arm
|
||||||
path: ${{runner.workspace}}/sdrpp_macos_arm.zip
|
path: ${{runner.workspace}}/sdrpp_macos_arm.zip
|
||||||
|
|
||||||
build_debian_bullseye_amd64:
|
build_debian_buster:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Create Docker Image
|
||||||
|
run: cd $GITHUB_WORKSPACE/docker_builds/debian_buster && docker build . --tag sdrpp_build
|
||||||
|
|
||||||
|
- name: Run Container
|
||||||
|
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
||||||
|
|
||||||
|
- name: Recover Deb Archive
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||||
|
|
||||||
|
- name: Save Deb Archive
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: sdrpp_debian_buster_amd64
|
||||||
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
|
build_debian_bullseye:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -248,29 +234,7 @@ jobs:
|
|||||||
name: sdrpp_debian_bullseye_amd64
|
name: sdrpp_debian_bullseye_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_debian_bullseye_aarch64:
|
build_debian_bookworm:
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bullseye && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_debian_bullseye_aarch64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_debian_bookworm_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -292,73 +256,7 @@ jobs:
|
|||||||
name: sdrpp_debian_bookworm_amd64
|
name: sdrpp_debian_bookworm_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_debian_bookworm_aarch64:
|
build_debian_sid:
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bookworm && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_debian_bookworm_aarch64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_debian_trixie_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_trixie && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_debian_trixie_amd64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_debian_trixie_aarch64:
|
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_trixie && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_debian_trixie_aarch64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_debian_sid_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -380,29 +278,7 @@ jobs:
|
|||||||
name: sdrpp_debian_sid_amd64
|
name: sdrpp_debian_sid_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_debian_sid_aarch64:
|
build_ubuntu_focal:
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_sid && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_debian_sid_aarch64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_ubuntu_focal_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -424,29 +300,7 @@ jobs:
|
|||||||
name: sdrpp_ubuntu_focal_amd64
|
name: sdrpp_ubuntu_focal_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_ubuntu_focal_aarch64:
|
build_ubuntu_jammy:
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Docker Image
|
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_focal && docker build . --tag sdrpp_build
|
|
||||||
|
|
||||||
- name: Run Container
|
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
|
||||||
working-directory: ${{runner.workspace}}
|
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
|
||||||
|
|
||||||
- name: Save Deb Archive
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdrpp_ubuntu_focal_aarch64
|
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
|
||||||
|
|
||||||
build_ubuntu_jammy_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -468,14 +322,14 @@ jobs:
|
|||||||
name: sdrpp_ubuntu_jammy_amd64
|
name: sdrpp_ubuntu_jammy_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_ubuntu_jammy_aarch64:
|
build_ubuntu_mantic:
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Create Docker Image
|
- name: Create Docker Image
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_jammy && docker build . --tag sdrpp_build
|
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_mantic && docker build . --tag sdrpp_build
|
||||||
|
|
||||||
- name: Run Container
|
- name: Run Container
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
||||||
@@ -487,10 +341,10 @@ jobs:
|
|||||||
- name: Save Deb Archive
|
- name: Save Deb Archive
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: sdrpp_ubuntu_jammy_aarch64
|
name: sdrpp_ubuntu_mantic_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_ubuntu_noble_amd64:
|
build_ubuntu_noble:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -512,27 +366,32 @@ jobs:
|
|||||||
name: sdrpp_ubuntu_noble_amd64
|
name: sdrpp_ubuntu_noble_amd64
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||||
|
|
||||||
build_ubuntu_noble_aarch64:
|
build_raspios_bullseye_armhf:
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ARM
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Create Docker Image
|
- name: Create Build Environment
|
||||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_noble && docker build . --tag sdrpp_build
|
run: rm -rf ${{runner.workspace}}/build && cmake -E make_directory ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Run Container
|
- name: Prepare CMake
|
||||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_USRP_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
|
|
||||||
- name: Recover Deb Archive
|
- name: Build
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
run: make VERBOSE=1 -j3
|
||||||
|
|
||||||
|
- name: Create Dev Archive
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
run: sh $GITHUB_WORKSPACE/make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev' && mv sdrpp_debian_amd64.deb sdrpp_debian_armhf.deb
|
||||||
|
|
||||||
- name: Save Deb Archive
|
- name: Save Deb Archive
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: sdrpp_ubuntu_noble_aarch64
|
name: sdrpp_raspios_bullseye_armhf
|
||||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
path: ${{runner.workspace}}/sdrpp_debian_armhf.deb
|
||||||
|
|
||||||
build_android:
|
build_android:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -562,26 +421,7 @@ jobs:
|
|||||||
path: ${{runner.workspace}}/sdrpp.apk
|
path: ${{runner.workspace}}/sdrpp.apk
|
||||||
|
|
||||||
create_full_archive:
|
create_full_archive:
|
||||||
needs: [
|
needs: ['build_windows', 'build_macos_intel', 'build_macos_arm', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_bookworm', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_ubuntu_mantic', 'build_ubuntu_noble', 'build_raspios_bullseye_armhf', 'build_android']
|
||||||
'build_windows',
|
|
||||||
'build_macos_intel',
|
|
||||||
'build_macos_arm',
|
|
||||||
'build_debian_bullseye_amd64',
|
|
||||||
'build_debian_bullseye_aarch64',
|
|
||||||
'build_debian_bookworm_amd64',
|
|
||||||
'build_debian_bookworm_aarch64',
|
|
||||||
'build_debian_trixie_amd64',
|
|
||||||
'build_debian_trixie_aarch64',
|
|
||||||
'build_debian_sid_amd64',
|
|
||||||
'build_debian_sid_aarch64',
|
|
||||||
'build_ubuntu_focal_amd64',
|
|
||||||
'build_ubuntu_focal_aarch64',
|
|
||||||
'build_ubuntu_jammy_amd64',
|
|
||||||
'build_ubuntu_jammy_aarch64',
|
|
||||||
'build_ubuntu_noble_amd64',
|
|
||||||
'build_ubuntu_noble_aarch64',
|
|
||||||
'build_android'
|
|
||||||
]
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -594,20 +434,15 @@ jobs:
|
|||||||
mv sdrpp_windows_x64/sdrpp_windows_x64.zip sdrpp_all/ &&
|
mv sdrpp_windows_x64/sdrpp_windows_x64.zip sdrpp_all/ &&
|
||||||
mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ &&
|
mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ &&
|
||||||
mv sdrpp_macos_arm/sdrpp_macos_arm.zip sdrpp_all/ &&
|
mv sdrpp_macos_arm/sdrpp_macos_arm.zip sdrpp_all/ &&
|
||||||
|
mv sdrpp_debian_buster_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_buster_amd64.deb &&
|
||||||
mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb &&
|
mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb &&
|
||||||
mv sdrpp_debian_bullseye_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_aarch64.deb &&
|
|
||||||
mv sdrpp_debian_bookworm_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_amd64.deb &&
|
mv sdrpp_debian_bookworm_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_amd64.deb &&
|
||||||
mv sdrpp_debian_bookworm_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_aarch64.deb &&
|
|
||||||
mv sdrpp_debian_trixie_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_trixie_amd64.deb &&
|
|
||||||
mv sdrpp_debian_trixie_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_trixie_aarch64.deb &&
|
|
||||||
mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb &&
|
mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb &&
|
||||||
mv sdrpp_debian_sid_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_aarch64.deb &&
|
|
||||||
mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb &&
|
mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb &&
|
||||||
mv sdrpp_ubuntu_focal_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_aarch64.deb &&
|
|
||||||
mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb &&
|
mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb &&
|
||||||
mv sdrpp_ubuntu_jammy_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_aarch64.deb &&
|
mv sdrpp_ubuntu_mantic_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_mantic_amd64.deb &&
|
||||||
mv sdrpp_ubuntu_noble_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_noble_amd64.deb &&
|
mv sdrpp_ubuntu_noble_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_noble_amd64.deb &&
|
||||||
mv sdrpp_ubuntu_noble_aarch64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_noble_aarch64.deb &&
|
mv sdrpp_raspios_bullseye_armhf/sdrpp_debian_armhf.deb sdrpp_all/sdrpp_raspios_bullseye_armhf.deb &&
|
||||||
mv sdrpp_android/sdrpp.apk sdrpp_all/sdrpp.apk
|
mv sdrpp_android/sdrpp.apk sdrpp_all/sdrpp.apk
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -17,7 +17,3 @@ m17_decoder/libcorrect
|
|||||||
SDR++.app
|
SDR++.app
|
||||||
android/deps
|
android/deps
|
||||||
android/app/assets
|
android/app/assets
|
||||||
source_modules/badgesdr_source
|
|
||||||
decoder_modules/mystery_decoder
|
|
||||||
decoder_modules/tetra_decoder
|
|
||||||
misc_modules/modulation_monitor
|
|
||||||
@@ -14,14 +14,9 @@ option(OPT_BUILD_AIRSPYHF_SOURCE "Build Airspy HF+ Source Module (Dependencies:
|
|||||||
option(OPT_BUILD_AUDIO_SOURCE "Build Audio Source Module (Dependencies: rtaudio)" ON)
|
option(OPT_BUILD_AUDIO_SOURCE "Build Audio Source Module (Dependencies: rtaudio)" ON)
|
||||||
option(OPT_BUILD_BADGESDR_SOURCE "Build BadgeSDR Source Module (Dependencies: libusb)" OFF)
|
option(OPT_BUILD_BADGESDR_SOURCE "Build BadgeSDR Source Module (Dependencies: libusb)" OFF)
|
||||||
option(OPT_BUILD_BLADERF_SOURCE "Build BladeRF Source Module (Dependencies: libbladeRF)" OFF)
|
option(OPT_BUILD_BLADERF_SOURCE "Build BladeRF Source Module (Dependencies: libbladeRF)" OFF)
|
||||||
option(OPT_BUILD_DRAGONLABS_SOURCE "Build Dragon Labs Source Module (Dependencies: libdlcr)" OFF)
|
|
||||||
option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
|
option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
|
||||||
option(OPT_BUILD_FOBOSSDR_SOURCE "Build FobosSDR Source Module (Dependencies: libfobos)" OFF)
|
|
||||||
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
|
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
|
||||||
option(OPT_BUILD_HAROGIC_SOURCE "Build Harogic Source Module (Dependencies: htra_api)" OFF)
|
|
||||||
option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON)
|
option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON)
|
||||||
option(OPT_BUILD_HYDRASDR_SOURCE "Build HydraSDR Source Module (Dependencies: libhydrasdr)" OFF)
|
|
||||||
option(OPT_BUILD_KCSDR_SOURCE "Build KCSDR Source Module (Dependencies: libkcsdr)" OFF)
|
|
||||||
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
|
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
|
||||||
option(OPT_BUILD_NETWORK_SOURCE "Build Network Source Module (no dependencies required)" ON)
|
option(OPT_BUILD_NETWORK_SOURCE "Build Network Source Module (no dependencies required)" ON)
|
||||||
option(OPT_BUILD_PERSEUS_SOURCE "Build Perseus Source Module (Dependencies: libperseus-sdr)" OFF)
|
option(OPT_BUILD_PERSEUS_SOURCE "Build Perseus Source Module (Dependencies: libperseus-sdr)" OFF)
|
||||||
@@ -46,16 +41,13 @@ option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Depend
|
|||||||
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
|
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
|
||||||
|
|
||||||
# Decoders
|
# Decoders
|
||||||
option(OPT_BUILD_ATV_DECODER "Build ATV decoder (no dependencies required)" ON)
|
option(OPT_BUILD_ATV_DECODER "Build ATV decoder (no dependencies required)" OFF)
|
||||||
option(OPT_BUILD_DAB_DECODER "Build the DAB/DAB+ decoder (no dependencies required)" OFF)
|
|
||||||
option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF)
|
option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF)
|
||||||
option(OPT_BUILD_KG_SSTV_DECODER "Build the KG SSTV (KG-STV) decoder module (no dependencies required)" OFF)
|
option(OPT_BUILD_KG_SSTV_DECODER "Build the KG SSTV (KG-STV) decoder module (no dependencies required)" OFF)
|
||||||
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (Dependencies: codec2)" OFF)
|
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (Dependencies: codec2)" OFF)
|
||||||
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
|
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
|
||||||
option(OPT_BUILD_PAGER_DECODER "Build the pager decoder module (no dependencies required)" ON)
|
option(OPT_BUILD_PAGER_DECODER "Build the pager decoder module (no dependencies required)" ON)
|
||||||
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
|
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
|
||||||
option(OPT_BUILD_RYFI_DECODER "RyFi data link decoder" OFF)
|
|
||||||
option(OPT_BUILD_VOR_RECEIVER "VOR beacon receiver" OFF)
|
|
||||||
option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF)
|
option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF)
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
@@ -144,38 +136,18 @@ if (OPT_BUILD_BLADERF_SOURCE)
|
|||||||
add_subdirectory("source_modules/bladerf_source")
|
add_subdirectory("source_modules/bladerf_source")
|
||||||
endif (OPT_BUILD_BLADERF_SOURCE)
|
endif (OPT_BUILD_BLADERF_SOURCE)
|
||||||
|
|
||||||
if (OPT_BUILD_DRAGONLABS_SOURCE)
|
|
||||||
add_subdirectory("source_modules/dragonlabs_source")
|
|
||||||
endif (OPT_BUILD_DRAGONLABS_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_FILE_SOURCE)
|
if (OPT_BUILD_FILE_SOURCE)
|
||||||
add_subdirectory("source_modules/file_source")
|
add_subdirectory("source_modules/file_source")
|
||||||
endif (OPT_BUILD_FILE_SOURCE)
|
endif (OPT_BUILD_FILE_SOURCE)
|
||||||
|
|
||||||
if (OPT_BUILD_FOBOSSDR_SOURCE)
|
|
||||||
add_subdirectory("source_modules/fobossdr_source")
|
|
||||||
endif (OPT_BUILD_FOBOSSDR_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_HACKRF_SOURCE)
|
if (OPT_BUILD_HACKRF_SOURCE)
|
||||||
add_subdirectory("source_modules/hackrf_source")
|
add_subdirectory("source_modules/hackrf_source")
|
||||||
endif (OPT_BUILD_HACKRF_SOURCE)
|
endif (OPT_BUILD_HACKRF_SOURCE)
|
||||||
|
|
||||||
if (OPT_BUILD_HAROGIC_SOURCE)
|
|
||||||
add_subdirectory("source_modules/harogic_source")
|
|
||||||
endif (OPT_BUILD_HAROGIC_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_HERMES_SOURCE)
|
if (OPT_BUILD_HERMES_SOURCE)
|
||||||
add_subdirectory("source_modules/hermes_source")
|
add_subdirectory("source_modules/hermes_source")
|
||||||
endif (OPT_BUILD_HERMES_SOURCE)
|
endif (OPT_BUILD_HERMES_SOURCE)
|
||||||
|
|
||||||
if (OPT_BUILD_HYDRASDR_SOURCE)
|
|
||||||
add_subdirectory("source_modules/hydrasdr_source")
|
|
||||||
endif (OPT_BUILD_HYDRASDR_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_KCSDR_SOURCE)
|
|
||||||
add_subdirectory("source_modules/kcsdr_source")
|
|
||||||
endif (OPT_BUILD_KCSDR_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_LIMESDR_SOURCE)
|
if (OPT_BUILD_LIMESDR_SOURCE)
|
||||||
add_subdirectory("source_modules/limesdr_source")
|
add_subdirectory("source_modules/limesdr_source")
|
||||||
endif (OPT_BUILD_LIMESDR_SOURCE)
|
endif (OPT_BUILD_LIMESDR_SOURCE)
|
||||||
@@ -208,10 +180,6 @@ if (OPT_BUILD_RTL_TCP_SOURCE)
|
|||||||
add_subdirectory("source_modules/rtl_tcp_source")
|
add_subdirectory("source_modules/rtl_tcp_source")
|
||||||
endif (OPT_BUILD_RTL_TCP_SOURCE)
|
endif (OPT_BUILD_RTL_TCP_SOURCE)
|
||||||
|
|
||||||
if (OPT_BUILD_SDDC_SOURCE)
|
|
||||||
add_subdirectory("source_modules/sddc_source")
|
|
||||||
endif (OPT_BUILD_SDDC_SOURCE)
|
|
||||||
|
|
||||||
if (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
if (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
||||||
add_subdirectory("source_modules/sdrpp_server_source")
|
add_subdirectory("source_modules/sdrpp_server_source")
|
||||||
endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
||||||
@@ -268,10 +236,6 @@ if (OPT_BUILD_ATV_DECODER)
|
|||||||
add_subdirectory("decoder_modules/atv_decoder")
|
add_subdirectory("decoder_modules/atv_decoder")
|
||||||
endif (OPT_BUILD_ATV_DECODER)
|
endif (OPT_BUILD_ATV_DECODER)
|
||||||
|
|
||||||
if (OPT_BUILD_DAB_DECODER)
|
|
||||||
add_subdirectory("decoder_modules/dab_decoder")
|
|
||||||
endif (OPT_BUILD_DAB_DECODER)
|
|
||||||
|
|
||||||
if (OPT_BUILD_FALCON9_DECODER)
|
if (OPT_BUILD_FALCON9_DECODER)
|
||||||
add_subdirectory("decoder_modules/falcon9_decoder")
|
add_subdirectory("decoder_modules/falcon9_decoder")
|
||||||
endif (OPT_BUILD_FALCON9_DECODER)
|
endif (OPT_BUILD_FALCON9_DECODER)
|
||||||
@@ -296,14 +260,6 @@ if (OPT_BUILD_RADIO)
|
|||||||
add_subdirectory("decoder_modules/radio")
|
add_subdirectory("decoder_modules/radio")
|
||||||
endif (OPT_BUILD_RADIO)
|
endif (OPT_BUILD_RADIO)
|
||||||
|
|
||||||
if (OPT_BUILD_RYFI_DECODER)
|
|
||||||
add_subdirectory("decoder_modules/ryfi_decoder")
|
|
||||||
endif (OPT_BUILD_RYFI_DECODER)
|
|
||||||
|
|
||||||
if (OPT_BUILD_VOR_RECEIVER)
|
|
||||||
add_subdirectory("decoder_modules/vor_receiver")
|
|
||||||
endif (OPT_BUILD_VOR_RECEIVER)
|
|
||||||
|
|
||||||
if (OPT_BUILD_WEATHER_SAT_DECODER)
|
if (OPT_BUILD_WEATHER_SAT_DECODER)
|
||||||
add_subdirectory("decoder_modules/weather_sat_decoder")
|
add_subdirectory("decoder_modules/weather_sat_decoder")
|
||||||
endif (OPT_BUILD_WEATHER_SAT_DECODER)
|
endif (OPT_BUILD_WEATHER_SAT_DECODER)
|
||||||
@@ -344,6 +300,7 @@ endif (OPT_BUILD_SCHEDULER)
|
|||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
add_executable(sdrpp "src/main.cpp" "win32/resources.rc")
|
add_executable(sdrpp "src/main.cpp" "win32/resources.rc")
|
||||||
|
add_executable(min_broken "min_broken/main.cpp" "win32/resources.rc")
|
||||||
else ()
|
else ()
|
||||||
add_executable(sdrpp "src/main.cpp")
|
add_executable(sdrpp "src/main.cpp")
|
||||||
endif ()
|
endif ()
|
||||||
@@ -352,6 +309,7 @@ target_link_libraries(sdrpp PRIVATE sdrpp_core)
|
|||||||
|
|
||||||
# Compiler arguments
|
# Compiler arguments
|
||||||
target_compile_options(sdrpp PRIVATE ${SDRPP_COMPILER_FLAGS})
|
target_compile_options(sdrpp PRIVATE ${SDRPP_COMPILER_FLAGS})
|
||||||
|
target_compile_options(min_broken PRIVATE ${SDRPP_COMPILER_FLAGS})
|
||||||
|
|
||||||
# Copy dynamic libs over
|
# Copy dynamic libs over
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
@@ -374,7 +332,6 @@ if (MSVC)
|
|||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
||||||
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.so\" \"$<TARGET_FILE_DIR:sdrpp>\")
|
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.so\" \"$<TARGET_FILE_DIR:sdrpp>\")
|
||||||
endif ()
|
endif ()
|
||||||
@@ -413,5 +370,3 @@ endif ()
|
|||||||
# Create uninstall target
|
# Create uninstall target
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake @ONLY)
|
||||||
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
|
||||||
# Create headers target
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ android {
|
|||||||
minSdkVersion 28
|
minSdkVersion 28
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.2.1"
|
versionName "1.2.0"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
arguments "-DOPT_BACKEND_GLFW=OFF", "-DOPT_BACKEND_ANDROID=ON", "-DOPT_BUILD_SOAPY_SOURCE=OFF", "-DOPT_BUILD_ANDROID_AUDIO_SINK=ON", "-DOPT_BUILD_AUDIO_SINK=OFF", "-DOPT_BUILD_DISCORD_PRESENCE=OFF", "-DOPT_BUILD_M17_DECODER=ON", "-DOPT_BUILD_PLUTOSDR_SOURCE=ON", "-DOPT_BUILD_AUDIO_SOURCE=OFF", "-DOPT_BUILD_HYDRASDR_SOURCE=ON"
|
arguments "-DOPT_BACKEND_GLFW=OFF", "-DOPT_BACKEND_ANDROID=ON", "-DOPT_BUILD_SOAPY_SOURCE=OFF", "-DOPT_BUILD_ANDROID_AUDIO_SINK=ON", "-DOPT_BUILD_AUDIO_SINK=OFF", "-DOPT_BUILD_DISCORD_PRESENCE=OFF", "-DOPT_BUILD_M17_DECODER=ON", "-DOPT_BUILD_PLUTOSDR_SOURCE=ON", "-DOPT_BUILD_AUDIO_SOURCE=OFF"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
# AI USE IS FORBIDDEN
|
|
||||||
|
|
||||||
Use of AI for the creation of code, pull requests or issues is forbidden.
|
|
||||||
|
|
||||||
Submitting code, pull requests or issues generated by AI will result in a permanent ban from all of my (Alexandre Rouma) repositories.
|
|
||||||
|
|
||||||
# Pull Requests
|
# Pull Requests
|
||||||
|
|
||||||
Code pull requests are **NOT welcome**. Please open an issue discussing potential bugfixes or feature requests instead.
|
Code pull requests are **NOT welcome**. Please open an issue discussing potential bugfixes or feature requests instead.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ namespace backend {
|
|||||||
extern const std::vector<DevVIDPID> AIRSPY_VIDPIDS;
|
extern const std::vector<DevVIDPID> AIRSPY_VIDPIDS;
|
||||||
extern const std::vector<DevVIDPID> AIRSPYHF_VIDPIDS;
|
extern const std::vector<DevVIDPID> AIRSPYHF_VIDPIDS;
|
||||||
extern const std::vector<DevVIDPID> HACKRF_VIDPIDS;
|
extern const std::vector<DevVIDPID> HACKRF_VIDPIDS;
|
||||||
extern const std::vector<DevVIDPID> HYDRASDR_VIDPIDS;
|
|
||||||
extern const std::vector<DevVIDPID> RTL_SDR_VIDPIDS;
|
extern const std::vector<DevVIDPID> RTL_SDR_VIDPIDS;
|
||||||
|
|
||||||
int getDeviceFD(int& vid, int& pid, const std::vector<DevVIDPID>& allowedVidPids);
|
int getDeviceFD(int& vid, int& pid, const std::vector<DevVIDPID>& allowedVidPids);
|
||||||
|
|||||||
@@ -408,11 +408,6 @@ namespace backend {
|
|||||||
{ 0x1d50, 0xcc15 }
|
{ 0x1d50, 0xcc15 }
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<DevVIDPID> HYDRASDR_VIDPIDS = {
|
|
||||||
{ 0x1d50, 0x60a1 },
|
|
||||||
{ 0x38af, 0x0001 }
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<DevVIDPID> RTL_SDR_VIDPIDS = {
|
const std::vector<DevVIDPID> RTL_SDR_VIDPIDS = {
|
||||||
{ 0x0bda, 0x2832 },
|
{ 0x0bda, 0x2832 },
|
||||||
{ 0x0bda, 0x2838 },
|
{ 0x0bda, 0x2838 },
|
||||||
|
|||||||
@@ -99,9 +99,6 @@ namespace backend {
|
|||||||
glfwWindowHint(GLFW_CLIENT_API, OPENGL_VERSIONS_IS_ES[i] ? GLFW_OPENGL_ES_API : GLFW_OPENGL_API);
|
glfwWindowHint(GLFW_CLIENT_API, OPENGL_VERSIONS_IS_ES[i] ? GLFW_OPENGL_ES_API : GLFW_OPENGL_API);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_VERSIONS_MAJOR[i]);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_VERSIONS_MAJOR[i]);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_VERSIONS_MINOR[i]);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_VERSIONS_MINOR[i]);
|
||||||
#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4)
|
|
||||||
glfwWindowHintString(GLFW_WAYLAND_APP_ID, "sdrpp");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create window with graphics context
|
// Create window with graphics context
|
||||||
monitor = glfwGetPrimaryMonitor();
|
monitor = glfwGetPrimaryMonitor();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(Correct C)
|
project(Correct C)
|
||||||
include(CheckLibraryExists)
|
include(CheckLibraryExists)
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
defConfig["menuElements"][3]["name"] = "Sinks";
|
defConfig["menuElements"][3]["name"] = "Sinks";
|
||||||
defConfig["menuElements"][3]["open"] = true;
|
defConfig["menuElements"][3]["open"] = true;
|
||||||
|
|
||||||
defConfig["menuElements"][4]["name"] = "Frequency Manager";
|
defConfig["menuElements"][3]["name"] = "Frequency Manager";
|
||||||
defConfig["menuElements"][4]["open"] = true;
|
defConfig["menuElements"][3]["open"] = true;
|
||||||
|
|
||||||
defConfig["menuElements"][5]["name"] = "VFO Color";
|
defConfig["menuElements"][4]["name"] = "VFO Color";
|
||||||
defConfig["menuElements"][5]["open"] = true;
|
defConfig["menuElements"][4]["open"] = true;
|
||||||
|
|
||||||
defConfig["menuElements"][6]["name"] = "Band Plan";
|
defConfig["menuElements"][6]["name"] = "Band Plan";
|
||||||
defConfig["menuElements"][6]["open"] = true;
|
defConfig["menuElements"][6]["open"] = true;
|
||||||
@@ -171,30 +171,18 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
defConfig["moduleInstances"]["Audio Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["Audio Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["BladeRF Source"]["module"] = "bladerf_source";
|
defConfig["moduleInstances"]["BladeRF Source"]["module"] = "bladerf_source";
|
||||||
defConfig["moduleInstances"]["BladeRF Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["BladeRF Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["Dragon Labs Source"]["module"] = "dragonlabs_source";
|
|
||||||
defConfig["moduleInstances"]["Dragon Labs Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["File Source"]["module"] = "file_source";
|
defConfig["moduleInstances"]["File Source"]["module"] = "file_source";
|
||||||
defConfig["moduleInstances"]["File Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["File Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["FobosSDR Source"]["module"] = "fobossdr_source";
|
|
||||||
defConfig["moduleInstances"]["FobosSDR Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["HackRF Source"]["module"] = "hackrf_source";
|
defConfig["moduleInstances"]["HackRF Source"]["module"] = "hackrf_source";
|
||||||
defConfig["moduleInstances"]["HackRF Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["HackRF Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["Harogic Source"]["module"] = "harogic_source";
|
|
||||||
defConfig["moduleInstances"]["Harogic Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["Hermes Source"]["module"] = "hermes_source";
|
defConfig["moduleInstances"]["Hermes Source"]["module"] = "hermes_source";
|
||||||
defConfig["moduleInstances"]["Hermes Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["Hermes Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["HydraSDR Source"]["module"] = "hydrasdr_source";
|
|
||||||
defConfig["moduleInstances"]["HydraSDR Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["LimeSDR Source"]["module"] = "limesdr_source";
|
defConfig["moduleInstances"]["LimeSDR Source"]["module"] = "limesdr_source";
|
||||||
defConfig["moduleInstances"]["LimeSDR Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["LimeSDR Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["Network Source"]["module"] = "network_source";
|
|
||||||
defConfig["moduleInstances"]["Network Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["PerseusSDR Source"]["module"] = "perseus_source";
|
|
||||||
defConfig["moduleInstances"]["PerseusSDR Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["PlutoSDR Source"]["module"] = "plutosdr_source";
|
defConfig["moduleInstances"]["PlutoSDR Source"]["module"] = "plutosdr_source";
|
||||||
defConfig["moduleInstances"]["PlutoSDR Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["PlutoSDR Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["RFNM Source"]["module"] = "rfnm_source";
|
defConfig["moduleInstances"]["PerseusSDR Source"]["module"] = "perseus_source";
|
||||||
defConfig["moduleInstances"]["RFNM Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["PerseusSDR Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["RFspace Source"]["module"] = "rfspace_source";
|
defConfig["moduleInstances"]["RFspace Source"]["module"] = "rfspace_source";
|
||||||
defConfig["moduleInstances"]["RFspace Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["RFspace Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["RTL-SDR Source"]["module"] = "rtl_sdr_source";
|
defConfig["moduleInstances"]["RTL-SDR Source"]["module"] = "rtl_sdr_source";
|
||||||
@@ -205,12 +193,8 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
defConfig["moduleInstances"]["SDRplay Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["SDRplay Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["SDR++ Server Source"]["module"] = "sdrpp_server_source";
|
defConfig["moduleInstances"]["SDR++ Server Source"]["module"] = "sdrpp_server_source";
|
||||||
defConfig["moduleInstances"]["SDR++ Server Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["SDR++ Server Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["Spectran HTTP Source"]["module"] = "spectran_http_source";
|
|
||||||
defConfig["moduleInstances"]["Spectran HTTP Source"]["enabled"] = true;
|
|
||||||
defConfig["moduleInstances"]["SpyServer Source"]["module"] = "spyserver_source";
|
defConfig["moduleInstances"]["SpyServer Source"]["module"] = "spyserver_source";
|
||||||
defConfig["moduleInstances"]["SpyServer Source"]["enabled"] = true;
|
defConfig["moduleInstances"]["SpyServer Source"]["enabled"] = true;
|
||||||
defConfig["moduleInstances"]["USRP Source"]["module"] = "usrp_source";
|
|
||||||
defConfig["moduleInstances"]["USRP Source"]["enabled"] = true;
|
|
||||||
|
|
||||||
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
|
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
|
||||||
defConfig["moduleInstances"]["Network Sink"] = "network_sink";
|
defConfig["moduleInstances"]["Network Sink"] = "network_sink";
|
||||||
@@ -236,19 +220,12 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
defConfig["modules"] = json::array();
|
defConfig["modules"] = json::array();
|
||||||
|
|
||||||
defConfig["offsets"]["SpyVerter"] = 120000000.0;
|
defConfig["offsetMode"] = (int)0; // Off
|
||||||
defConfig["offsets"]["Ham-It-Up"] = 125000000.0;
|
defConfig["offset"] = 0.0;
|
||||||
defConfig["offsets"]["MMDS S-band (1998MHz)"] = -1998000000.0;
|
|
||||||
defConfig["offsets"]["DK5AV X-Band"] = -6800000000.0;
|
|
||||||
defConfig["offsets"]["Ku LNB (9750MHz)"] = -9750000000.0;
|
|
||||||
defConfig["offsets"]["Ku LNB (10700MHz)"] = -10700000000.0;
|
|
||||||
|
|
||||||
defConfig["selectedOffset"] = "None";
|
|
||||||
defConfig["manualOffset"] = 0.0;
|
|
||||||
defConfig["showMenu"] = true;
|
defConfig["showMenu"] = true;
|
||||||
defConfig["showWaterfall"] = true;
|
defConfig["showWaterfall"] = true;
|
||||||
defConfig["source"] = "";
|
defConfig["source"] = "";
|
||||||
defConfig["decimation"] = 1;
|
defConfig["decimationPower"] = 0;
|
||||||
defConfig["iqCorrection"] = false;
|
defConfig["iqCorrection"] = false;
|
||||||
defConfig["invertIQ"] = false;
|
defConfig["invertIQ"] = false;
|
||||||
|
|
||||||
@@ -299,7 +276,6 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
core::configManager.conf["modules"][modCount++] = "airspyhf_source.so";
|
core::configManager.conf["modules"][modCount++] = "airspyhf_source.so";
|
||||||
core::configManager.conf["modules"][modCount++] = "hackrf_source.so";
|
core::configManager.conf["modules"][modCount++] = "hackrf_source.so";
|
||||||
core::configManager.conf["modules"][modCount++] = "hermes_source.so";
|
core::configManager.conf["modules"][modCount++] = "hermes_source.so";
|
||||||
core::configManager.conf["modules"][modCount++] = "hydrasdr_source.so";
|
|
||||||
core::configManager.conf["modules"][modCount++] = "plutosdr_source.so";
|
core::configManager.conf["modules"][modCount++] = "plutosdr_source.so";
|
||||||
core::configManager.conf["modules"][modCount++] = "rfspace_source.so";
|
core::configManager.conf["modules"][modCount++] = "rfspace_source.so";
|
||||||
core::configManager.conf["modules"][modCount++] = "rtl_sdr_source.so";
|
core::configManager.conf["modules"][modCount++] = "rtl_sdr_source.so";
|
||||||
@@ -330,18 +306,12 @@ int sdrpp_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Remove unused elements
|
// Remove unused elements
|
||||||
auto items = core::configManager.conf.items();
|
auto items = core::configManager.conf.items();
|
||||||
auto newConf = core::configManager.conf;
|
|
||||||
bool configCorrected = false;
|
|
||||||
for (auto const& item : items) {
|
for (auto const& item : items) {
|
||||||
if (!defConfig.contains(item.key())) {
|
if (!defConfig.contains(item.key())) {
|
||||||
flog::info("Unused key in config {0}, repairing", item.key());
|
flog::info("Unused key in config {0}, repairing", item.key());
|
||||||
newConf.erase(item.key());
|
core::configManager.conf.erase(item.key());
|
||||||
configCorrected = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (configCorrected) {
|
|
||||||
core::configManager.conf = newConf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update to new module representation in config if needed
|
// Update to new module representation in config if needed
|
||||||
for (auto [_name, inst] : core::configManager.conf["moduleInstances"].items()) {
|
for (auto [_name, inst] : core::configManager.conf["moduleInstances"].items()) {
|
||||||
|
|||||||
@@ -37,12 +37,9 @@ namespace sdrpp_credits {
|
|||||||
const char* hardwareDonators[] = {
|
const char* hardwareDonators[] = {
|
||||||
"Aaronia AG",
|
"Aaronia AG",
|
||||||
"Airspy",
|
"Airspy",
|
||||||
"Alex 4Z5LV",
|
|
||||||
"Analog Devices",
|
"Analog Devices",
|
||||||
"CaribouLabs",
|
"CaribouLabs",
|
||||||
"Deepace",
|
|
||||||
"Ettus Research",
|
"Ettus Research",
|
||||||
"Harogic",
|
|
||||||
"Howard Su",
|
"Howard Su",
|
||||||
"MicroPhase",
|
"MicroPhase",
|
||||||
"Microtelecom",
|
"Microtelecom",
|
||||||
@@ -50,7 +47,6 @@ namespace sdrpp_credits {
|
|||||||
"Nuand",
|
"Nuand",
|
||||||
"RFNM",
|
"RFNM",
|
||||||
"RFspace",
|
"RFspace",
|
||||||
"RigExpert",
|
|
||||||
"RTL-SDRblog",
|
"RTL-SDRblog",
|
||||||
"SDRplay"
|
"SDRplay"
|
||||||
};
|
};
|
||||||
@@ -70,18 +66,15 @@ namespace sdrpp_credits {
|
|||||||
"Flinger Films",
|
"Flinger Films",
|
||||||
"Frank Werner (HB9FXQ)",
|
"Frank Werner (HB9FXQ)",
|
||||||
"gringogrigio",
|
"gringogrigio",
|
||||||
"Jandro",
|
|
||||||
"Jeff Moe",
|
"Jeff Moe",
|
||||||
"Joe Cupano",
|
"Joe Cupano",
|
||||||
"KD1SQ",
|
"KD1SQ",
|
||||||
"Kezza",
|
"Kezza",
|
||||||
"Krys Kamieniecki",
|
"Krys Kamieniecki",
|
||||||
"Lee Donaghy",
|
"Lee Donaghy",
|
||||||
"Lee (KD1SQ)",
|
"Lee KD1SQ",
|
||||||
".lozenge. (Hank Hill)",
|
".lozenge. (Hank Hill)",
|
||||||
"Martin Herren (HB9FXX)",
|
"Martin Herren (HB9FXX)",
|
||||||
"NeoVilsonWong",
|
|
||||||
"Nitin (VU2JEK)",
|
|
||||||
"ON4MU",
|
"ON4MU",
|
||||||
"Passion-Radio.com",
|
"Passion-Radio.com",
|
||||||
"Paul Maine",
|
"Paul Maine",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <volk/volk.h>
|
#include <volk/volk.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace dsp::buffer {
|
namespace dsp::buffer {
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|||||||
@@ -163,10 +163,10 @@ namespace dsp {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Processor<T, T>* blockBefore(Processor<T, T>* block) {
|
Processor<T, T>* blockBefore(Processor<T, T>* block) {
|
||||||
Processor<T, T>* prev = NULL;
|
// TODO: This is wrong and must be fixed when I get more time
|
||||||
for (auto& ln : links) {
|
for (auto& ln : links) {
|
||||||
if (ln == block) { return prev; }
|
if (ln == block) { return NULL; }
|
||||||
if (states[ln]) { prev = ln; }
|
if (states[ln]) { return ln; }
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,17 +22,18 @@ namespace dsp::demod {
|
|||||||
dsp::taps::free(filterTaps);
|
dsp::taps::free(filterTaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(dsp::stream<dsp::complex_t>* in, double samplerate, double bandwidth, bool lowPass) {
|
void init(dsp::stream<dsp::complex_t>* in, double samplerate, double bandwidth, bool lowPass, bool highPass) {
|
||||||
_samplerate = samplerate;
|
_samplerate = samplerate;
|
||||||
_bandwidth = bandwidth;
|
_bandwidth = bandwidth;
|
||||||
_lowPass = lowPass;
|
_lowPass = lowPass;
|
||||||
|
_highPass = highPass;
|
||||||
|
|
||||||
demod.init(NULL, bandwidth / 2.0, _samplerate);
|
demod.init(NULL, bandwidth / 2.0, _samplerate);
|
||||||
loadDummyTaps();
|
loadDummyTaps();
|
||||||
fir.init(NULL, filterTaps);
|
fir.init(NULL, filterTaps);
|
||||||
|
|
||||||
// Initialize taps
|
// Initialize taps
|
||||||
updateFilter(lowPass);
|
updateFilter(lowPass, highPass);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, float>) {
|
if constexpr (std::is_same_v<T, float>) {
|
||||||
demod.out.free();
|
demod.out.free();
|
||||||
@@ -48,7 +49,7 @@ namespace dsp::demod {
|
|||||||
base_type::tempStop();
|
base_type::tempStop();
|
||||||
_samplerate = samplerate;
|
_samplerate = samplerate;
|
||||||
demod.setDeviation(_bandwidth / 2.0, _samplerate);
|
demod.setDeviation(_bandwidth / 2.0, _samplerate);
|
||||||
updateFilter(_lowPass);
|
updateFilter(_lowPass, _highPass);
|
||||||
base_type::tempStart();
|
base_type::tempStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,13 +59,19 @@ namespace dsp::demod {
|
|||||||
if (bandwidth == _bandwidth) { return; }
|
if (bandwidth == _bandwidth) { return; }
|
||||||
_bandwidth = bandwidth;
|
_bandwidth = bandwidth;
|
||||||
demod.setDeviation(_bandwidth / 2.0, _samplerate);
|
demod.setDeviation(_bandwidth / 2.0, _samplerate);
|
||||||
updateFilter(_lowPass);
|
updateFilter(_lowPass, _highPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLowPass(bool lowPass) {
|
void setLowPass(bool lowPass) {
|
||||||
assert(base_type::_block_init);
|
assert(base_type::_block_init);
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
updateFilter(lowPass);
|
updateFilter(lowPass, _highPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHighPass(bool highPass) {
|
||||||
|
assert(base_type::_block_init);
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
|
updateFilter(_lowPass, highPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
@@ -79,14 +86,14 @@ namespace dsp::demod {
|
|||||||
inline int process(int count, dsp::complex_t* in, T* out) {
|
inline int process(int count, dsp::complex_t* in, T* out) {
|
||||||
if constexpr (std::is_same_v<T, float>) {
|
if constexpr (std::is_same_v<T, float>) {
|
||||||
demod.process(count, in, out);
|
demod.process(count, in, out);
|
||||||
if (_lowPass) {
|
if (filtering) {
|
||||||
std::lock_guard<std::mutex> lck(filterMtx);
|
std::lock_guard<std::mutex> lck(filterMtx);
|
||||||
fir.process(count, out, out);
|
fir.process(count, out, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<T, stereo_t>) {
|
if constexpr (std::is_same_v<T, stereo_t>) {
|
||||||
demod.process(count, in, demod.out.writeBuf);
|
demod.process(count, in, demod.out.writeBuf);
|
||||||
if (_lowPass) {
|
if (filtering) {
|
||||||
std::lock_guard<std::mutex> lck(filterMtx);
|
std::lock_guard<std::mutex> lck(filterMtx);
|
||||||
fir.process(count, demod.out.writeBuf, demod.out.writeBuf);
|
fir.process(count, demod.out.writeBuf, demod.out.writeBuf);
|
||||||
}
|
}
|
||||||
@@ -107,17 +114,25 @@ namespace dsp::demod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateFilter(bool lowPass) {
|
void updateFilter(bool lowPass, bool highPass) {
|
||||||
std::lock_guard<std::mutex> lck(filterMtx);
|
std::lock_guard<std::mutex> lck(filterMtx);
|
||||||
|
|
||||||
// Update values
|
// Update values
|
||||||
_lowPass = lowPass;
|
_lowPass = lowPass;
|
||||||
|
_highPass = highPass;
|
||||||
|
filtering = (lowPass || highPass);
|
||||||
|
|
||||||
// Free filter taps
|
// Free filter taps
|
||||||
dsp::taps::free(filterTaps);
|
dsp::taps::free(filterTaps);
|
||||||
|
|
||||||
// Generate filter depending on the low pass settings
|
// Generate filter depending on low and high pass settings
|
||||||
if (_lowPass) {
|
if (_lowPass && _highPass) {
|
||||||
|
filterTaps = dsp::taps::bandPass<float>(300.0, _bandwidth / 2.0, 100.0, _samplerate);
|
||||||
|
}
|
||||||
|
else if (_highPass) {
|
||||||
|
filterTaps = dsp::taps::highPass(300.0, 100.0, _samplerate);
|
||||||
|
}
|
||||||
|
else if (_lowPass) {
|
||||||
filterTaps = dsp::taps::lowPass(_bandwidth / 2.0, (_bandwidth / 2.0) * 0.1, _samplerate);
|
filterTaps = dsp::taps::lowPass(_bandwidth / 2.0, (_bandwidth / 2.0) * 0.1, _samplerate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -137,6 +152,7 @@ namespace dsp::demod {
|
|||||||
double _samplerate;
|
double _samplerate;
|
||||||
double _bandwidth;
|
double _bandwidth;
|
||||||
bool _lowPass;
|
bool _lowPass;
|
||||||
|
bool _highPass;
|
||||||
bool filtering;
|
bool filtering;
|
||||||
|
|
||||||
Quadrature demod;
|
Quadrature demod;
|
||||||
|
|||||||
@@ -1,303 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "../channel/rx_vfo.h"
|
|
||||||
#include "../demod/quadrature.h"
|
|
||||||
#include "../filter/fir.h"
|
|
||||||
#include "../taps/high_pass.h"
|
|
||||||
#include <fftw3.h>
|
|
||||||
#include <map>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#define CTCSS_DECODE_SAMPLERATE 500//250.0
|
|
||||||
#define CTCSS_DECODE_BANDWIDTH 200.0
|
|
||||||
#define CTCSS_DECODE_OFFSET 160.55
|
|
||||||
|
|
||||||
namespace dsp::noise_reduction {
|
|
||||||
enum CTCSSTone {
|
|
||||||
/**
|
|
||||||
* Indicates that any valid tone will let audio through.
|
|
||||||
*/
|
|
||||||
CTCSS_TONE_ANY = -2,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that no tone is being received, or to act as a decoder only, letting audio through continuously.
|
|
||||||
*/
|
|
||||||
CTCSS_TONE_NONE = -1,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CTCSS Tone Frequency.
|
|
||||||
*/
|
|
||||||
CTCSS_TONE_67Hz,
|
|
||||||
CTCSS_TONE_69_3Hz,
|
|
||||||
CTCSS_TONE_71_9Hz,
|
|
||||||
CTCSS_TONE_74_4Hz,
|
|
||||||
CTCSS_TONE_77Hz,
|
|
||||||
CTCSS_TONE_79_7Hz,
|
|
||||||
CTCSS_TONE_82_5Hz,
|
|
||||||
CTCSS_TONE_85_4Hz,
|
|
||||||
CTCSS_TONE_88_5Hz,
|
|
||||||
CTCSS_TONE_91_5Hz,
|
|
||||||
CTCSS_TONE_94_8Hz,
|
|
||||||
CTCSS_TONE_97_4Hz,
|
|
||||||
CTCSS_TONE_100Hz,
|
|
||||||
CTCSS_TONE_103_5Hz,
|
|
||||||
CTCSS_TONE_107_2Hz,
|
|
||||||
CTCSS_TONE_110_9Hz,
|
|
||||||
CTCSS_TONE_114_8Hz,
|
|
||||||
CTCSS_TONE_118_8Hz,
|
|
||||||
CTCSS_TONE_123Hz,
|
|
||||||
CTCSS_TONE_127_3Hz,
|
|
||||||
CTCSS_TONE_131_8Hz,
|
|
||||||
CTCSS_TONE_136_5Hz,
|
|
||||||
CTCSS_TONE_141_3Hz,
|
|
||||||
CTCSS_TONE_146_2Hz,
|
|
||||||
CTCSS_TONE_150Hz,
|
|
||||||
CTCSS_TONE_151_4Hz,
|
|
||||||
CTCSS_TONE_156_7Hz,
|
|
||||||
CTCSS_TONE_159_8Hz,
|
|
||||||
CTCSS_TONE_162_2Hz,
|
|
||||||
CTCSS_TONE_165_5Hz,
|
|
||||||
CTCSS_TONE_167_9Hz,
|
|
||||||
CTCSS_TONE_171_3Hz,
|
|
||||||
CTCSS_TONE_173_8Hz,
|
|
||||||
CTCSS_TONE_177_3Hz,
|
|
||||||
CTCSS_TONE_179_9Hz,
|
|
||||||
CTCSS_TONE_183_5Hz,
|
|
||||||
CTCSS_TONE_186_2Hz,
|
|
||||||
CTCSS_TONE_189_9Hz,
|
|
||||||
CTCSS_TONE_192_8Hz,
|
|
||||||
CTCSS_TONE_196_6Hz,
|
|
||||||
CTCSS_TONE_199_5Hz,
|
|
||||||
CTCSS_TONE_203_5Hz,
|
|
||||||
CTCSS_TONE_206_5Hz,
|
|
||||||
CTCSS_TONE_210_7Hz,
|
|
||||||
CTCSS_TONE_218_1Hz,
|
|
||||||
CTCSS_TONE_225_7Hz,
|
|
||||||
CTCSS_TONE_229_1Hz,
|
|
||||||
CTCSS_TONE_233_6Hz,
|
|
||||||
CTCSS_TONE_241_8Hz,
|
|
||||||
CTCSS_TONE_250_3Hz,
|
|
||||||
CTCSS_TONE_254_1Hz,
|
|
||||||
_CTCSS_TONE_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
const float CTCSS_TONES[_CTCSS_TONE_COUNT] = {
|
|
||||||
67.0f,
|
|
||||||
69.3f,
|
|
||||||
71.9f,
|
|
||||||
74.4f,
|
|
||||||
77.0f,
|
|
||||||
79.7f,
|
|
||||||
82.5f,
|
|
||||||
85.4f,
|
|
||||||
88.5f,
|
|
||||||
91.5f,
|
|
||||||
94.8f,
|
|
||||||
97.4f,
|
|
||||||
100.0f,
|
|
||||||
103.5f,
|
|
||||||
107.2f,
|
|
||||||
110.9f,
|
|
||||||
114.8f,
|
|
||||||
118.8f,
|
|
||||||
123.0f,
|
|
||||||
127.3f,
|
|
||||||
131.8f,
|
|
||||||
136.5f,
|
|
||||||
141.3f,
|
|
||||||
146.2f,
|
|
||||||
150.0f,
|
|
||||||
151.4f,
|
|
||||||
156.7f,
|
|
||||||
159.8f,
|
|
||||||
162.2f,
|
|
||||||
165.5f,
|
|
||||||
167.9f,
|
|
||||||
171.3f,
|
|
||||||
173.8f,
|
|
||||||
177.3f,
|
|
||||||
179.9f,
|
|
||||||
183.5f,
|
|
||||||
186.2f,
|
|
||||||
189.9f,
|
|
||||||
192.8f,
|
|
||||||
196.6f,
|
|
||||||
199.5f,
|
|
||||||
203.5f,
|
|
||||||
206.5f,
|
|
||||||
210.7f,
|
|
||||||
218.1f,
|
|
||||||
225.7f,
|
|
||||||
229.1f,
|
|
||||||
233.6f,
|
|
||||||
241.8f,
|
|
||||||
250.3f,
|
|
||||||
254.1f
|
|
||||||
};
|
|
||||||
|
|
||||||
class CTCSSSquelch : public Processor<stereo_t, stereo_t> {
|
|
||||||
using base_type = Processor<stereo_t, stereo_t>;
|
|
||||||
public:
|
|
||||||
CTCSSSquelch() {}
|
|
||||||
|
|
||||||
CTCSSSquelch(stream<stereo_t>* in, double samplerate) { init(in, samplerate); }
|
|
||||||
|
|
||||||
~CTCSSSquelch() {
|
|
||||||
// If not initialized, do nothing
|
|
||||||
if (!base_type::_block_init) { return; }
|
|
||||||
|
|
||||||
// Stop the DSP thread
|
|
||||||
base_type::stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(stream<stereo_t>* in, double samplerate) {
|
|
||||||
// Save settings
|
|
||||||
_samplerate = samplerate;
|
|
||||||
|
|
||||||
// Create dummy taps just for initialization
|
|
||||||
float dummy[1] = { 1.0f };
|
|
||||||
auto dummyTaps = dsp::taps::fromArray(1, dummy);
|
|
||||||
|
|
||||||
// Initialize the DDC and FM demod
|
|
||||||
ddc.init(NULL, samplerate, CTCSS_DECODE_SAMPLERATE, CTCSS_DECODE_BANDWIDTH, CTCSS_DECODE_OFFSET);
|
|
||||||
fm.init(NULL, 1.0, CTCSS_DECODE_SAMPLERATE);
|
|
||||||
|
|
||||||
// Initilize the base block class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSamplerate(double samplerate) {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
base_type::tempStop();
|
|
||||||
_samplerate = samplerate;
|
|
||||||
ddc.setInSamplerate(samplerate);
|
|
||||||
base_type::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRequiredTone(CTCSSTone tone) {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
requiredTone = tone;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTCSSTone getCurrentTone() {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
return currentTone;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int process(int count, const stereo_t* in, stereo_t* out) {
|
|
||||||
// Shift and resample to the correct samplerate
|
|
||||||
int ddcOutCount = ddc.process(count, (complex_t*)in, ddc.out.writeBuf);
|
|
||||||
|
|
||||||
// FM Demod the CTCSS tone
|
|
||||||
fm.process(ddcOutCount, ddc.out.writeBuf, fm.out.writeBuf);
|
|
||||||
|
|
||||||
// Get the required tone
|
|
||||||
const CTCSSTone rtone = requiredTone;
|
|
||||||
|
|
||||||
// Detect the tone frequency
|
|
||||||
for (int i = 0; i < ddcOutCount; i++) {
|
|
||||||
// Compute the running mean
|
|
||||||
const float val = fm.out.writeBuf[i];
|
|
||||||
mean = 0.95f*mean + 0.05f*val;
|
|
||||||
|
|
||||||
// Compute the running variance
|
|
||||||
const float err = val - mean;
|
|
||||||
var = 0.95f*var + 0.05f*err*err;
|
|
||||||
|
|
||||||
// Run a schmitt trigger on the variance
|
|
||||||
bool nvarOk = varOk ? (var < 1100.0f) : (var < 1000.0f);
|
|
||||||
|
|
||||||
// Check if the tone has to be rematched
|
|
||||||
if (nvarOk && (!varOk || mean < minFreq || mean > maxFreq)) {
|
|
||||||
// Compute the absolute frequency
|
|
||||||
float freq = mean + CTCSS_DECODE_OFFSET;
|
|
||||||
|
|
||||||
// Check it against the known tones
|
|
||||||
if (freq < CTCSS_TONES[0] - 2.5) {
|
|
||||||
currentTone = CTCSS_TONE_NONE;
|
|
||||||
}
|
|
||||||
else if (freq > CTCSS_TONES[_CTCSS_TONE_COUNT-1] + 2.5) {
|
|
||||||
currentTone = CTCSS_TONE_NONE;
|
|
||||||
}
|
|
||||||
else if (freq < CTCSS_TONES[0]) {
|
|
||||||
currentTone = (CTCSSTone)0;
|
|
||||||
}
|
|
||||||
else if (freq > CTCSS_TONES[_CTCSS_TONE_COUNT-1]) {
|
|
||||||
currentTone = (CTCSSTone)(_CTCSS_TONE_COUNT-1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int a = 0;
|
|
||||||
int b = _CTCSS_TONE_COUNT-1;
|
|
||||||
while (b - a > 1) {
|
|
||||||
int c = (a + b) >> 1;
|
|
||||||
((CTCSS_TONES[c] < freq) ? a : b) = c;
|
|
||||||
}
|
|
||||||
currentTone = (CTCSSTone)((freq - CTCSS_TONES[a] < CTCSS_TONES[b] - freq) ? a : b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the mute status
|
|
||||||
mute = !(currentTone == rtone || (currentTone != CTCSS_TONE_NONE && rtone == CTCSS_TONE_ANY));
|
|
||||||
|
|
||||||
// Unmuted the audio if needed
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
// Recompute min and max freq if a valid tone is detected
|
|
||||||
if (currentTone != CTCSS_TONE_NONE) {
|
|
||||||
float c = CTCSS_TONES[currentTone];
|
|
||||||
float l = (currentTone > CTCSS_TONE_67Hz) ? CTCSS_TONES[currentTone - 1] : c - 2.5f;
|
|
||||||
float r = (currentTone < CTCSS_TONE_254_1Hz) ? CTCSS_TONES[currentTone + 1] : c + 2.5f;
|
|
||||||
minFreq = (l+c) / 2.0f;
|
|
||||||
maxFreq = (r+c) / 2.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a rising edge on the variance
|
|
||||||
if (!nvarOk && varOk) {
|
|
||||||
// Mute the audio
|
|
||||||
// TODO
|
|
||||||
mute = true;
|
|
||||||
currentTone = CTCSS_TONE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the new variance state
|
|
||||||
varOk = nvarOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG ONLY
|
|
||||||
if ((rtone != CTCSS_TONE_NONE) && mute) {
|
|
||||||
memset(out, 0, count * sizeof(stereo_t));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(out, in, count * sizeof(stereo_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!base_type::out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
double _samplerate;
|
|
||||||
std::atomic<CTCSSTone> requiredTone = CTCSS_TONE_ANY;
|
|
||||||
|
|
||||||
float mean = 0.0f;
|
|
||||||
float var = 0.0f;
|
|
||||||
bool varOk = false;
|
|
||||||
float minFreq = 0.0f;
|
|
||||||
float maxFreq = 0.0f;
|
|
||||||
bool mute = true;
|
|
||||||
std::atomic<CTCSSTone> currentTone = CTCSS_TONE_NONE;
|
|
||||||
|
|
||||||
channel::RxVFO ddc;
|
|
||||||
demod::Quadrature fm;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
// TODO: Rewrite better!!!!!
|
// TODO: Rewrite better!!!!!
|
||||||
namespace dsp::noise_reduction {
|
namespace dsp::noise_reduction {
|
||||||
class PowerSquelch : public Processor<complex_t, complex_t> {
|
class Squelch : public Processor<complex_t, complex_t> {
|
||||||
using base_type = Processor<complex_t, complex_t>;
|
using base_type = Processor<complex_t, complex_t>;
|
||||||
public:
|
public:
|
||||||
PowerSquelch() {}
|
Squelch() {}
|
||||||
|
|
||||||
PowerSquelch(stream<complex_t>* in, double level) {}
|
Squelch(stream<complex_t>* in, double level) {}
|
||||||
|
|
||||||
~PowerSquelch() {
|
~Squelch() {
|
||||||
if (!base_type::_block_init) { return; }
|
if (!base_type::_block_init) { return; }
|
||||||
base_type::stop();
|
base_type::stop();
|
||||||
buffer::free(normBuffer);
|
buffer::free(normBuffer);
|
||||||
@@ -31,11 +31,8 @@ namespace dsp::noise_reduction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int process(int count, const complex_t* in, complex_t* out) {
|
inline int process(int count, const complex_t* in, complex_t* out) {
|
||||||
// Compute the amplitude of each sample
|
float sum;
|
||||||
volk_32fc_magnitude_32f(normBuffer, (lv_32fc_t*)in, count);
|
volk_32fc_magnitude_32f(normBuffer, (lv_32fc_t*)in, count);
|
||||||
|
|
||||||
// Compute the mean amplitude
|
|
||||||
float sum = 0.0f;
|
|
||||||
volk_32f_accumulator_s32f(&sum, normBuffer, count);
|
volk_32f_accumulator_s32f(&sum, normBuffer, count);
|
||||||
sum /= (float)count;
|
sum /= (float)count;
|
||||||
|
|
||||||
@@ -49,6 +46,8 @@ namespace dsp::noise_reduction {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DEFAULT_PROC_RUN();
|
||||||
|
|
||||||
int run() {
|
int run() {
|
||||||
int count = base_type::_in->read();
|
int count = base_type::_in->read();
|
||||||
if (count < 0) { return -1; }
|
if (count < 0) { return -1; }
|
||||||
@@ -5,6 +5,8 @@ namespace dsp {
|
|||||||
template <class T>
|
template <class T>
|
||||||
class Source : public block {
|
class Source : public block {
|
||||||
public:
|
public:
|
||||||
|
Source() {}
|
||||||
|
|
||||||
Source() { init(); }
|
Source() { init(); }
|
||||||
|
|
||||||
virtual ~Source() {}
|
virtual ~Source() {}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <volk/volk.h>
|
#include <volk/volk.h>
|
||||||
#include "../buffer/buffer.h"
|
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|||||||
@@ -5,120 +5,113 @@
|
|||||||
#include <gui/main_window.h>
|
#include <gui/main_window.h>
|
||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <utils/optionlist.h>
|
|
||||||
#include <gui/dialogs/dialog_box.h>
|
|
||||||
|
|
||||||
namespace sourcemenu {
|
namespace sourcemenu {
|
||||||
|
int offsetMode = 0;
|
||||||
int sourceId = 0;
|
int sourceId = 0;
|
||||||
EventHandler<std::string> sourcesChangedHandler;
|
double customOffset = 0.0;
|
||||||
EventHandler<std::string> sourceUnregisterHandler;
|
double effectiveOffset = 0.0;
|
||||||
OptionList<std::string, std::string> sources;
|
int decimationPower = 0;
|
||||||
std::string selectedSource;
|
|
||||||
|
|
||||||
int decimId = 0;
|
|
||||||
OptionList<int, int> decimations;
|
|
||||||
|
|
||||||
bool iqCorrection = false;
|
bool iqCorrection = false;
|
||||||
bool invertIQ = false;
|
bool invertIQ = false;
|
||||||
|
|
||||||
int offsetId = 0;
|
EventHandler<std::string> sourceRegisteredHandler;
|
||||||
double manualOffset = 0.0;
|
EventHandler<std::string> sourceUnregisterHandler;
|
||||||
std::string selectedOffset;
|
EventHandler<std::string> sourceUnregisteredHandler;
|
||||||
double effectiveOffset = 0.0;
|
|
||||||
OptionList<std::string, double> offsets;
|
|
||||||
std::map<std::string, double> namedOffsets;
|
|
||||||
|
|
||||||
bool showAddOffsetDialog = false;
|
std::vector<std::string> sourceNames;
|
||||||
char newOffsetName[1024];
|
std::string sourceNamesTxt;
|
||||||
double newOffset = 0.0;
|
std::string selectedSource;
|
||||||
|
|
||||||
bool showDelOffsetDialog = false;
|
|
||||||
std::string delOffsetName = "";
|
|
||||||
|
|
||||||
// Offset IDs
|
|
||||||
enum {
|
enum {
|
||||||
OFFSET_ID_NONE,
|
OFFSET_MODE_NONE,
|
||||||
OFFSET_ID_MANUAL,
|
OFFSET_MODE_CUSTOM,
|
||||||
OFFSET_ID_CUSTOM_BASE
|
OFFSET_MODE_SPYVERTER,
|
||||||
|
OFFSET_MODE_HAM_IT_UP,
|
||||||
|
OFFSET_MODE_MMDS_SB_1998,
|
||||||
|
OFFSET_MODE_DK5AV_XB,
|
||||||
|
OFFSET_MODE_KU_LNB_9750,
|
||||||
|
OFFSET_MODE_KU_LNB_10700,
|
||||||
|
_OFFSET_MODE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
void updateOffset() {
|
const char* offsetModesTxt = "None\0"
|
||||||
// Compute the effective offset
|
"Custom\0"
|
||||||
switch (offsetId) {
|
"SpyVerter\0"
|
||||||
case OFFSET_ID_NONE:
|
"Ham-It-Up\0"
|
||||||
effectiveOffset = 0;
|
"MMDS S-band (1998MHz)\0"
|
||||||
break;
|
"DK5AV X-Band\0"
|
||||||
case OFFSET_ID_MANUAL:
|
"Ku LNB (9750MHz)\0"
|
||||||
effectiveOffset = manualOffset;
|
"Ku LNB (10700MHz)\0";
|
||||||
break;
|
|
||||||
default:
|
|
||||||
effectiveOffset = namedOffsets[offsets.name(offsetId)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply it
|
const char* decimationStages = "None\0"
|
||||||
|
"2\0"
|
||||||
|
"4\0"
|
||||||
|
"8\0"
|
||||||
|
"16\0"
|
||||||
|
"32\0"
|
||||||
|
"64\0";
|
||||||
|
|
||||||
|
void updateOffset() {
|
||||||
|
if (offsetMode == OFFSET_MODE_CUSTOM) { effectiveOffset = customOffset; }
|
||||||
|
else if (offsetMode == OFFSET_MODE_SPYVERTER) {
|
||||||
|
effectiveOffset = 120000000;
|
||||||
|
} // 120MHz Up-conversion
|
||||||
|
else if (offsetMode == OFFSET_MODE_HAM_IT_UP) {
|
||||||
|
effectiveOffset = 125000000;
|
||||||
|
} // 125MHz Up-conversion
|
||||||
|
else if (offsetMode == OFFSET_MODE_MMDS_SB_1998) {
|
||||||
|
effectiveOffset = -1998000000;
|
||||||
|
} // 1.998GHz Down-conversion
|
||||||
|
else if (offsetMode == OFFSET_MODE_DK5AV_XB) {
|
||||||
|
effectiveOffset = -6800000000;
|
||||||
|
} // 6.8GHz Down-conversion
|
||||||
|
else if (offsetMode == OFFSET_MODE_KU_LNB_9750) {
|
||||||
|
effectiveOffset = -9750000000;
|
||||||
|
} // 9.750GHz Down-conversion
|
||||||
|
else if (offsetMode == OFFSET_MODE_KU_LNB_10700) {
|
||||||
|
effectiveOffset = -10700000000;
|
||||||
|
} // 10.7GHz Down-conversion
|
||||||
|
else {
|
||||||
|
effectiveOffset = 0;
|
||||||
|
}
|
||||||
sigpath::sourceManager.setTuningOffset(effectiveOffset);
|
sigpath::sourceManager.setTuningOffset(effectiveOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectOffsetById(int id) {
|
|
||||||
// Update the offset mode
|
|
||||||
offsetId = id;
|
|
||||||
selectedOffset = offsets.name(id);
|
|
||||||
|
|
||||||
// Update the offset
|
|
||||||
updateOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void selectOffsetByName(const std::string& name) {
|
|
||||||
// If the name doesn't exist, select 'None'
|
|
||||||
if (!offsets.nameExists(name)) {
|
|
||||||
selectOffsetById(OFFSET_ID_NONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select using the ID associated with the name
|
|
||||||
selectOffsetById(offsets.nameId(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
void refreshSources() {
|
void refreshSources() {
|
||||||
// Get sources
|
sourceNames = sigpath::sourceManager.getSourceNames();
|
||||||
auto sourceNames = sigpath::sourceManager.getSourceNames();
|
sourceNamesTxt.clear();
|
||||||
|
|
||||||
// Define source options
|
|
||||||
sources.clear();
|
|
||||||
for (auto name : sourceNames) {
|
for (auto name : sourceNames) {
|
||||||
sources.define(name, name, name);
|
sourceNamesTxt += name;
|
||||||
|
sourceNamesTxt += '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectSource(std::string name) {
|
void selectSource(std::string name) {
|
||||||
// If there is no source, give up
|
if (sourceNames.empty()) {
|
||||||
if (sources.empty()) {
|
|
||||||
sourceId = 0;
|
|
||||||
selectedSource.clear();
|
selectedSource.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto it = std::find(sourceNames.begin(), sourceNames.end(), name);
|
||||||
|
if (it == sourceNames.end()) {
|
||||||
|
selectSource(sourceNames[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sourceId = std::distance(sourceNames.begin(), it);
|
||||||
|
selectedSource = sourceNames[sourceId];
|
||||||
|
sigpath::sourceManager.selectSource(sourceNames[sourceId]);
|
||||||
|
}
|
||||||
|
|
||||||
// If a source with the given name doesn't exist, select the first source instead
|
void onSourceRegistered(std::string name, void* ctx) {
|
||||||
if (!sources.valueExists(name)) {
|
refreshSources();
|
||||||
selectSource(sources.value(0));
|
|
||||||
|
if (selectedSource.empty()) {
|
||||||
|
sourceId = 0;
|
||||||
|
selectSource(sourceNames[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the GUI variables
|
sourceId = std::distance(sourceNames.begin(), std::find(sourceNames.begin(), sourceNames.end(), selectedSource));
|
||||||
sourceId = sources.valueId(name);
|
|
||||||
selectedSource = name;
|
|
||||||
|
|
||||||
// Select the source module
|
|
||||||
sigpath::sourceManager.selectSource(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onSourcesChanged(std::string name, void* ctx) {
|
|
||||||
// Update the source list
|
|
||||||
refreshSources();
|
|
||||||
|
|
||||||
// Reselect the current source
|
|
||||||
selectSource(selectedSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSourceUnregister(std::string name, void* ctx) {
|
void onSourceUnregister(std::string name, void* ctx) {
|
||||||
@@ -127,173 +120,60 @@ namespace sourcemenu {
|
|||||||
// TODO: Stop everything
|
// TODO: Stop everything
|
||||||
}
|
}
|
||||||
|
|
||||||
void reloadOffsets() {
|
void onSourceUnregistered(std::string name, void* ctx) {
|
||||||
// Clear list
|
refreshSources();
|
||||||
offsets.clear();
|
|
||||||
namedOffsets.clear();
|
|
||||||
|
|
||||||
// Define special offset modes
|
if (sourceNames.empty()) {
|
||||||
offsets.define("None", OFFSET_ID_NONE);
|
selectedSource = "";
|
||||||
offsets.define("Manual", OFFSET_ID_MANUAL);
|
return;
|
||||||
|
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.acquire();
|
|
||||||
|
|
||||||
// Load custom offsets
|
|
||||||
auto ofs = core::configManager.conf["offsets"].items();
|
|
||||||
for (auto& o : ofs) {
|
|
||||||
namedOffsets[o.key()] = (double)o.value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define custom offsets
|
if (name == selectedSource) {
|
||||||
for (auto& [name, offset] : namedOffsets) {
|
sourceId = std::clamp<int>(sourceId, 0, sourceNames.size() - 1);
|
||||||
offsets.define(name, offsets.size());
|
selectSource(sourceNames[sourceId]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the config file
|
sourceId = std::distance(sourceNames.begin(), std::find(sourceNames.begin(), sourceNames.end(), selectedSource));
|
||||||
core::configManager.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
// Load offset modes
|
|
||||||
reloadOffsets();
|
|
||||||
|
|
||||||
// Define decimation values
|
|
||||||
decimations.define(1, "None", 1);
|
|
||||||
decimations.define(2, "2x", 2);
|
|
||||||
decimations.define(4, "4x", 4);
|
|
||||||
decimations.define(8, "8x", 8);
|
|
||||||
decimations.define(16, "16x", 16);
|
|
||||||
decimations.define(32, "32x", 32);
|
|
||||||
decimations.define(64, "64x", 64);
|
|
||||||
|
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
|
std::string selected = core::configManager.conf["source"];
|
||||||
// Load other settings
|
customOffset = core::configManager.conf["offset"];
|
||||||
std::string selectedSource = core::configManager.conf["source"];
|
offsetMode = core::configManager.conf["offsetMode"];
|
||||||
manualOffset = core::configManager.conf["manualOffset"];
|
decimationPower = core::configManager.conf["decimationPower"];
|
||||||
std::string selectedOffset = core::configManager.conf["selectedOffset"];
|
|
||||||
iqCorrection = core::configManager.conf["iqCorrection"];
|
iqCorrection = core::configManager.conf["iqCorrection"];
|
||||||
invertIQ = core::configManager.conf["invertIQ"];
|
invertIQ = core::configManager.conf["invertIQ"];
|
||||||
int decimation = core::configManager.conf["decimation"];
|
|
||||||
if (decimations.keyExists(decimation)) {
|
|
||||||
decimId = decimations.keyId(decimation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the config file
|
|
||||||
core::configManager.release();
|
|
||||||
|
|
||||||
// Select the source module
|
|
||||||
refreshSources();
|
|
||||||
selectSource(selectedSource);
|
|
||||||
|
|
||||||
// Update frontend settings
|
|
||||||
sigpath::iqFrontEnd.setDCBlocking(iqCorrection);
|
sigpath::iqFrontEnd.setDCBlocking(iqCorrection);
|
||||||
sigpath::iqFrontEnd.setInvertIQ(invertIQ);
|
sigpath::iqFrontEnd.setInvertIQ(invertIQ);
|
||||||
sigpath::iqFrontEnd.setDecimation(decimations.value(decimId));
|
updateOffset();
|
||||||
selectOffsetByName(selectedOffset);
|
|
||||||
|
|
||||||
// Register handlers
|
refreshSources();
|
||||||
sourcesChangedHandler.handler = onSourcesChanged;
|
selectSource(selected);
|
||||||
|
sigpath::iqFrontEnd.setDecimation(1 << decimationPower);
|
||||||
|
|
||||||
|
sourceRegisteredHandler.handler = onSourceRegistered;
|
||||||
sourceUnregisterHandler.handler = onSourceUnregister;
|
sourceUnregisterHandler.handler = onSourceUnregister;
|
||||||
sigpath::sourceManager.onSourceRegistered.bindHandler(&sourcesChangedHandler);
|
sourceUnregisteredHandler.handler = onSourceUnregistered;
|
||||||
|
sigpath::sourceManager.onSourceRegistered.bindHandler(&sourceRegisteredHandler);
|
||||||
sigpath::sourceManager.onSourceUnregister.bindHandler(&sourceUnregisterHandler);
|
sigpath::sourceManager.onSourceUnregister.bindHandler(&sourceUnregisterHandler);
|
||||||
sigpath::sourceManager.onSourceUnregistered.bindHandler(&sourcesChangedHandler);
|
sigpath::sourceManager.onSourceUnregistered.bindHandler(&sourceUnregisteredHandler);
|
||||||
}
|
|
||||||
|
|
||||||
void addOffset(const std::string& name, double offset) {
|
core::configManager.release();
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.acquire();
|
|
||||||
|
|
||||||
// Define a new offset
|
|
||||||
core::configManager.conf["offsets"][name] = offset;
|
|
||||||
|
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.release(true);
|
|
||||||
|
|
||||||
// Reload the offsets
|
|
||||||
reloadOffsets();
|
|
||||||
|
|
||||||
// Attempt to re-select the same one
|
|
||||||
selectOffsetByName(selectedOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void delOffset(const std::string& name) {
|
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.acquire();
|
|
||||||
|
|
||||||
// Define a new offset
|
|
||||||
core::configManager.conf["offsets"].erase(name);
|
|
||||||
|
|
||||||
// Acquire the config file
|
|
||||||
core::configManager.release(true);
|
|
||||||
|
|
||||||
// Reload the offsets
|
|
||||||
reloadOffsets();
|
|
||||||
|
|
||||||
// Attempt to re-select the same one
|
|
||||||
selectOffsetByName(selectedOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool addOffsetDialog() {
|
|
||||||
bool open = true;
|
|
||||||
gui::mainWindow.lockWaterfallControls = true;
|
|
||||||
|
|
||||||
float menuWidth = ImGui::GetContentRegionAvail().x;
|
|
||||||
|
|
||||||
const char* id = "Add offset##sdrpp_add_offset_dialog_";
|
|
||||||
ImGui::OpenPopup(id);
|
|
||||||
|
|
||||||
if (ImGui::BeginPopup(id, ImGuiWindowFlags_NoResize)) {
|
|
||||||
ImGui::LeftLabel("Name");
|
|
||||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
|
||||||
ImGui::InputText("##sdrpp_add_offset_name", newOffsetName, 1023);
|
|
||||||
|
|
||||||
ImGui::LeftLabel("Offset");
|
|
||||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
|
||||||
ImGui::InputDouble("##sdrpp_add_offset_offset", &newOffset);
|
|
||||||
|
|
||||||
bool nameExists = offsets.nameExists(newOffsetName);
|
|
||||||
bool reservedName = !strcmp(newOffsetName, "None") || !strcmp(newOffsetName, "Manual");
|
|
||||||
bool denyApply = !newOffsetName[0] || nameExists || reservedName;
|
|
||||||
|
|
||||||
if (nameExists) {
|
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "An offset with the given name already exists.");
|
|
||||||
}
|
|
||||||
else if (reservedName) {
|
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "The given name is reserved.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (denyApply) { style::beginDisabled(); }
|
|
||||||
if (ImGui::Button("Apply")) {
|
|
||||||
addOffset(newOffsetName, newOffset);
|
|
||||||
open = false;
|
|
||||||
}
|
|
||||||
if (denyApply) { style::endDisabled(); }
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Cancel")) {
|
|
||||||
open = false;
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
return open;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(void* ctx) {
|
void draw(void* ctx) {
|
||||||
float itemWidth = ImGui::GetContentRegionAvail().x;
|
float itemWidth = ImGui::GetContentRegionAvail().x;
|
||||||
float lineHeight = ImGui::GetTextLineHeightWithSpacing();
|
|
||||||
float spacing = lineHeight - ImGui::GetTextLineHeight();
|
|
||||||
bool running = gui::mainWindow.sdrIsRunning();
|
bool running = gui::mainWindow.sdrIsRunning();
|
||||||
|
|
||||||
if (running) { style::beginDisabled(); }
|
if (running) { style::beginDisabled(); }
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(itemWidth);
|
ImGui::SetNextItemWidth(itemWidth);
|
||||||
if (ImGui::Combo("##source", &sourceId, sources.txt)) {
|
if (ImGui::Combo("##source", &sourceId, sourceNamesTxt.c_str())) {
|
||||||
std::string newSource = sources.value(sourceId);
|
selectSource(sourceNames[sourceId]);
|
||||||
selectSource(newSource);
|
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
core::configManager.conf["source"] = newSource;
|
core::configManager.conf["source"] = sourceNames[sourceId];
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,45 +196,21 @@ namespace sourcemenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::LeftLabel("Offset mode");
|
ImGui::LeftLabel("Offset mode");
|
||||||
ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX() - 2.0f*(lineHeight + 1.5f*spacing));
|
ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX());
|
||||||
if (ImGui::Combo("##_sdrpp_offset", &offsetId, offsets.txt)) {
|
if (ImGui::Combo("##_sdrpp_offset_mode", &offsetMode, offsetModesTxt)) {
|
||||||
selectOffsetById(offsetId);
|
|
||||||
core::configManager.acquire();
|
|
||||||
core::configManager.conf["selectedOffset"] = offsets.key(offsetId);
|
|
||||||
core::configManager.release(true);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - spacing);
|
|
||||||
if (offsetId < OFFSET_ID_CUSTOM_BASE) { ImGui::BeginDisabled(); }
|
|
||||||
if (ImGui::Button("-##_sdrpp_offset_del_", ImVec2(lineHeight + 0.5f*spacing, 0))) {
|
|
||||||
delOffsetName = selectedOffset;
|
|
||||||
showDelOffsetDialog = true;
|
|
||||||
}
|
|
||||||
if (offsetId < OFFSET_ID_CUSTOM_BASE) { ImGui::EndDisabled(); }
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - spacing);
|
|
||||||
if (ImGui::Button("+##_sdrpp_offset_add_", ImVec2(lineHeight + 0.5f*spacing, 0))) {
|
|
||||||
strcpy(newOffsetName, "New Offset");
|
|
||||||
showAddOffsetDialog = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset delete confirmation
|
|
||||||
if (ImGui::GenericDialog("sdrpp_del_offset_confirm", showDelOffsetDialog, GENERIC_DIALOG_BUTTONS_YES_NO, []() {
|
|
||||||
ImGui::Text("Deleting offset named \"%s\". Are you sure?", delOffsetName.c_str());
|
|
||||||
}) == GENERIC_DIALOG_BUTTON_YES) {
|
|
||||||
delOffset(delOffsetName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset add diaglog
|
|
||||||
if (showAddOffsetDialog) { showAddOffsetDialog = addOffsetDialog(); }
|
|
||||||
|
|
||||||
ImGui::LeftLabel("Offset");
|
|
||||||
ImGui::FillWidth();
|
|
||||||
if (offsetId == OFFSET_ID_MANUAL) {
|
|
||||||
if (ImGui::InputDouble("##freq_offset", &manualOffset, 1.0, 100.0)) {
|
|
||||||
updateOffset();
|
updateOffset();
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
core::configManager.conf["manualOffset"] = manualOffset;
|
core::configManager.conf["offsetMode"] = offsetMode;
|
||||||
|
core::configManager.release(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::LeftLabel("Offset");
|
||||||
|
ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX());
|
||||||
|
if (offsetMode == OFFSET_MODE_CUSTOM) {
|
||||||
|
if (ImGui::InputDouble("##freq_offset", &customOffset, 1.0, 100.0)) {
|
||||||
|
updateOffset();
|
||||||
|
core::configManager.acquire();
|
||||||
|
core::configManager.conf["offset"] = customOffset;
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,11 +222,11 @@ namespace sourcemenu {
|
|||||||
|
|
||||||
if (running) { style::beginDisabled(); }
|
if (running) { style::beginDisabled(); }
|
||||||
ImGui::LeftLabel("Decimation");
|
ImGui::LeftLabel("Decimation");
|
||||||
ImGui::FillWidth();
|
ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX());
|
||||||
if (ImGui::Combo("##source_decim", &decimId, decimations.txt)) {
|
if (ImGui::Combo("##source_decim", &decimationPower, decimationStages)) {
|
||||||
sigpath::iqFrontEnd.setDecimation(decimations.value(decimId));
|
sigpath::iqFrontEnd.setDecimation(1 << decimationPower);
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
core::configManager.conf["decimation"] = decimations.key(decimId);
|
core::configManager.conf["decimationPower"] = decimationPower;
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
if (running) { style::endDisabled(); }
|
if (running) { style::endDisabled(); }
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <backend.h>
|
#include <backend.h>
|
||||||
#include <utils/hrfreq.h>
|
|
||||||
|
|
||||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
@@ -91,7 +90,6 @@ void FrequencySelect::moveCursorToDigit(int i) {
|
|||||||
|
|
||||||
void FrequencySelect::draw() {
|
void FrequencySelect::draw() {
|
||||||
auto window = ImGui::GetCurrentWindow();
|
auto window = ImGui::GetCurrentWindow();
|
||||||
auto io = ImGui::GetIO();
|
|
||||||
widgetPos = ImGui::GetWindowContentRegionMin();
|
widgetPos = ImGui::GetWindowContentRegionMin();
|
||||||
ImVec2 cursorPos = ImGui::GetCursorPos();
|
ImVec2 cursorPos = ImGui::GetCursorPos();
|
||||||
widgetPos.x += window->Pos.x + cursorPos.x;
|
widgetPos.x += window->Pos.x + cursorPos.x;
|
||||||
@@ -134,7 +132,7 @@ void FrequencySelect::draw() {
|
|||||||
ImVec2 mousePos = ImGui::GetMousePos();
|
ImVec2 mousePos = ImGui::GetMousePos();
|
||||||
bool leftClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
bool leftClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||||
bool rightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
|
bool rightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
|
||||||
int mw = io.MouseWheel;
|
int mw = ImGui::GetIO().MouseWheel;
|
||||||
bool onDigit = false;
|
bool onDigit = false;
|
||||||
bool hovered = false;
|
bool hovered = false;
|
||||||
|
|
||||||
@@ -176,7 +174,7 @@ void FrequencySelect::draw() {
|
|||||||
moveCursorToDigit(i + 1);
|
moveCursorToDigit(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto chars = io.InputQueueCharacters;
|
auto chars = ImGui::GetIO().InputQueueCharacters;
|
||||||
|
|
||||||
// For each keyboard characters, type it
|
// For each keyboard characters, type it
|
||||||
for (int j = 0; j < chars.Size; j++) {
|
for (int j = 0; j < chars.Size; j++) {
|
||||||
@@ -196,34 +194,6 @@ void FrequencySelect::draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
digitHovered = hovered;
|
digitHovered = hovered;
|
||||||
|
|
||||||
if (isInArea(mousePos, digitTopMins[0], digitBottomMaxs[11])) {
|
|
||||||
bool shortcutKey = io.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiKeyModFlags_Super) : (io.KeyMods == ImGuiKeyModFlags_Ctrl);
|
|
||||||
bool ctrlOnly = (io.KeyMods == ImGuiKeyModFlags_Ctrl);
|
|
||||||
bool shiftOnly = (io.KeyMods == ImGuiKeyModFlags_Shift);
|
|
||||||
bool copy = ((shortcutKey && ImGui::IsKeyPressed(ImGuiKey_C)) || (ctrlOnly && ImGui::IsKeyPressed(ImGuiKey_Insert)));
|
|
||||||
bool paste = ((shortcutKey && ImGui::IsKeyPressed(ImGuiKey_V)) || (shiftOnly && ImGui::IsKeyPressed(ImGuiKey_Insert)));
|
|
||||||
if (copy) {
|
|
||||||
// Convert the freqency to a string
|
|
||||||
std::string freqStr = hrfreq::toString(frequency);
|
|
||||||
|
|
||||||
// Write it to the clipboard
|
|
||||||
ImGui::SetClipboardText(freqStr.c_str());
|
|
||||||
}
|
|
||||||
if (paste) {
|
|
||||||
// Attempt to parse the clipboard as a number
|
|
||||||
const char* clip = ImGui::GetClipboardText();
|
|
||||||
|
|
||||||
// If the clipboard is not empty, attempt to parse it
|
|
||||||
if (clip) {
|
|
||||||
double newFreq;
|
|
||||||
if (hrfreq::fromString(clip, newFreq)) {
|
|
||||||
setFrequency(abs(newFreq));
|
|
||||||
frequencyChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t freq = 0;
|
uint64_t freq = 0;
|
||||||
|
|||||||
@@ -52,4 +52,15 @@ namespace ImGui {
|
|||||||
bufferMtx.unlock();
|
bufferMtx.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolDiagram::setCount(int count) {
|
||||||
|
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||||
|
delete[] buffer;
|
||||||
|
buffer = new float[count];
|
||||||
|
sampleCount = count;
|
||||||
|
memset(buffer, 0, sampleCount * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SymbolDiagram::getCount() {
|
||||||
|
return sampleCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,10 @@ namespace ImGui {
|
|||||||
|
|
||||||
void releaseBuffer();
|
void releaseBuffer();
|
||||||
|
|
||||||
|
void setCount(int count);
|
||||||
|
|
||||||
|
int getCount();
|
||||||
|
|
||||||
std::vector<float> lines;
|
std::vector<float> lines;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ namespace ImGui {
|
|||||||
viewBandwidth = 1.0;
|
viewBandwidth = 1.0;
|
||||||
wholeBandwidth = 1.0;
|
wholeBandwidth = 1.0;
|
||||||
|
|
||||||
updatePallette(DEFAULT_COLOR_MAP, 13);
|
//updatePallette(DEFAULT_COLOR_MAP, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterFall::init() {
|
void WaterFall::init() {
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ void SourceManager::tune(double freq) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: No need to always retune the hardware in Panadapter mode
|
// TODO: No need to always retune the hardware in Panadapter mode
|
||||||
selectedHandler->tuneHandler(abs(((tuneMode == TuningMode::NORMAL) ? (freq + tuneOffset) : ifFreq)), selectedHandler->ctx);
|
selectedHandler->tuneHandler(((tuneMode == TuningMode::NORMAL) ? freq : ifFreq) + tuneOffset, selectedHandler->ctx);
|
||||||
onRetune.emit(freq + tuneOffset);
|
onRetune.emit(freq);
|
||||||
currentFreq = freq;
|
currentFreq = freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
#include "hrfreq.h"
|
|
||||||
#include <utils/flog.h>
|
|
||||||
|
|
||||||
namespace hrfreq {
|
|
||||||
|
|
||||||
|
|
||||||
std::string toString(double freq) {
|
|
||||||
// Determine the scale
|
|
||||||
int maxDecimals = 0;
|
|
||||||
const char* suffix = "Hz";
|
|
||||||
if (freq >= 1e9) {
|
|
||||||
freq /= 1e9;
|
|
||||||
maxDecimals = 9;
|
|
||||||
suffix = "GHz";
|
|
||||||
}
|
|
||||||
else if (freq >= 1e6) {
|
|
||||||
freq /= 1e6;
|
|
||||||
maxDecimals = 6;
|
|
||||||
suffix = "MHz";
|
|
||||||
}
|
|
||||||
else if (freq >= 1e3) {
|
|
||||||
freq /= 1e3;
|
|
||||||
maxDecimals = 3;
|
|
||||||
suffix = "KHz";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to string (TODO: Not sure if limiting the decimals rounds)
|
|
||||||
char numBuf[128];
|
|
||||||
int numLen = sprintf(numBuf, "%0.*lf", maxDecimals, freq);
|
|
||||||
|
|
||||||
// If there is a decimal point, remove the useless zeros
|
|
||||||
if (maxDecimals) {
|
|
||||||
for (int i = numLen-1; i >= 0; i--) {
|
|
||||||
bool dot = (numBuf[i] == '.');
|
|
||||||
if (numBuf[i] != '0' && !dot) { break; }
|
|
||||||
numBuf[i] = 0;
|
|
||||||
if (dot) { break; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Concat the suffix
|
|
||||||
char finalBuf[128];
|
|
||||||
sprintf(finalBuf, "%s%s", numBuf, suffix);
|
|
||||||
|
|
||||||
// Return the final string
|
|
||||||
return finalBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNumeric(char c) {
|
|
||||||
return std::isdigit(c) || c == '+' || c == '-' || c == '.' || c == ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fromString(const std::string& str, double& freq) {
|
|
||||||
// Skip non-numeric characters
|
|
||||||
int i = 0;
|
|
||||||
char c;
|
|
||||||
for (; i < str.size(); i++) {
|
|
||||||
if (isNumeric(str[i])) { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the numeric part
|
|
||||||
std::string numeric;
|
|
||||||
for (; i < str.size(); i++) {
|
|
||||||
// Get the character
|
|
||||||
c = str[i];
|
|
||||||
|
|
||||||
// If it's a letter, stop
|
|
||||||
if (std::isalpha(c)) { break; }
|
|
||||||
|
|
||||||
// If isn't numeric, skip it
|
|
||||||
if (!isNumeric(c)) { continue; }
|
|
||||||
|
|
||||||
// If it's a comma, skip it for now. This enforces a dot as a decimal point
|
|
||||||
if (c == ',') { continue; }
|
|
||||||
|
|
||||||
// Add the character to the numeric string
|
|
||||||
numeric += c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to parse the numeric part
|
|
||||||
double num;
|
|
||||||
try {
|
|
||||||
num = std::stod(numeric);
|
|
||||||
}
|
|
||||||
catch (const std::exception& e) {
|
|
||||||
flog::error("Failed to parse numeric part: '{}'", numeric);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no more text is available, assume the numeric part gives a frequency in Hz
|
|
||||||
if (i == str.size()) {
|
|
||||||
flog::warn("No unit given, assuming it's Hz");
|
|
||||||
freq = num;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale the numeric value depending on the first scale character
|
|
||||||
char scale = std::toupper(str[i]);
|
|
||||||
switch (scale) {
|
|
||||||
case 'G':
|
|
||||||
num *= 1e9;
|
|
||||||
break;
|
|
||||||
case 'M':
|
|
||||||
num *= 1e6;
|
|
||||||
break;
|
|
||||||
case 'K':
|
|
||||||
num *= 1e3;
|
|
||||||
break;
|
|
||||||
case 'H':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
flog::warn("Unknown frequency scale: '{}'", scale);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the frequency
|
|
||||||
freq = num;
|
|
||||||
return true; // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace hrfreq {
|
|
||||||
/**
|
|
||||||
* Convert a frequency to a human-readable string.
|
|
||||||
* @param freq Frequency in Hz.
|
|
||||||
* @return Human-readable representation of the frequency.
|
|
||||||
*/
|
|
||||||
std::string toString(double freq);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a human-readable representation of a frequency to a frequency value.
|
|
||||||
* @param str String containing the human-readable frequency.
|
|
||||||
* @param freq Value to write the decoded frequency to.
|
|
||||||
* @return True on success, false otherwise.
|
|
||||||
*/
|
|
||||||
bool fromString(const std::string& str, double& freq);
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERSION_STR "1.3.0"
|
#define VERSION_STR "1.2.0"
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <dsp/processor.h>
|
|
||||||
#include <dsp/math/fast_atan2.h>
|
|
||||||
#include <dsp/math/hz_to_rads.h>
|
|
||||||
#include <dsp/math/normalize_phase.h>
|
|
||||||
|
|
||||||
namespace dsp::demod {
|
|
||||||
class Amplitude : public Processor<complex_t, float> {
|
|
||||||
using base_type = Processor<complex_t, float>;
|
|
||||||
public:
|
|
||||||
Amplitude() {}
|
|
||||||
|
|
||||||
Amplitude(stream<complex_t>* in, double deviation) { init(in, deviation); }
|
|
||||||
|
|
||||||
Amplitude(stream<complex_t>* in, double deviation, double samplerate) { init(in, deviation, samplerate); }
|
|
||||||
|
|
||||||
|
|
||||||
virtual void init(stream<complex_t>* in, double deviation) {
|
|
||||||
_invDeviation = 1.0 / deviation;
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void init(stream<complex_t>* in, double deviation, double samplerate) {
|
|
||||||
init(in, math::hzToRads(deviation, samplerate));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeviation(double deviation) {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
_invDeviation = 1.0 / deviation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeviation(double deviation, double samplerate) {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
_invDeviation = 1.0 / math::hzToRads(deviation, samplerate);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int process(int count, complex_t* in, float* out) {
|
|
||||||
volk_32fc_magnitude_32f(out, (lv_32fc_t*)in, count);
|
|
||||||
volk_32f_s32f_multiply_32f(out, out, -1.0f, count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
phase = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!base_type::out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
float _invDeviation;
|
|
||||||
float phase = 0.0f;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
617 + 6 -> I
|
|
||||||
|
|
||||||
304 + 6 -> II
|
|
||||||
|
|
||||||
616 + 6 -> III
|
|
||||||
|
|
||||||
305 + 6 -> IV
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
304
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
|
|
||||||
616
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
313
|
|
||||||
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
0
|
|
||||||
|
|
||||||
304
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
616
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
313
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
0
|
|
||||||
304
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
616
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
313
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
0
|
|
||||||
304
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
616
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
313
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
0
|
|
||||||
304
|
|
||||||
305
|
|
||||||
306
|
|
||||||
307
|
|
||||||
308
|
|
||||||
309
|
|
||||||
310
|
|
||||||
311
|
|
||||||
312
|
|
||||||
616
|
|
||||||
617
|
|
||||||
618
|
|
||||||
619
|
|
||||||
620
|
|
||||||
621
|
|
||||||
622
|
|
||||||
623
|
|
||||||
624
|
|
||||||
63
decoder_modules/atv_decoder/src/chroma_pll.h
Normal file
63
decoder_modules/atv_decoder/src/chroma_pll.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <dsp/loop/pll.h>
|
||||||
|
#include "chrominance_filter.h"
|
||||||
|
|
||||||
|
// TODO: Should be 60 but had to try something
|
||||||
|
#define BURST_START (63+CHROMA_FIR_DELAY)
|
||||||
|
#define BURST_END (BURST_START+28)
|
||||||
|
|
||||||
|
#define A_PHASE ((135.0/180.0)*FL_M_PI)
|
||||||
|
#define B_PHASE ((-135.0/180.0)*FL_M_PI)
|
||||||
|
|
||||||
|
namespace dsp::loop {
|
||||||
|
class ChromaPLL : public PLL {
|
||||||
|
using base_type = PLL;
|
||||||
|
public:
|
||||||
|
ChromaPLL() {}
|
||||||
|
|
||||||
|
ChromaPLL(stream<complex_t>* in, double bandwidth, double initPhase = 0.0, double initFreq = 0.0, double minFreq = -FL_M_PI, double maxFreq = FL_M_PI) {
|
||||||
|
base_type::init(in, bandwidth, initFreq, initPhase, minFreq, maxFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int process(int count, complex_t* in, complex_t* out, bool aphase = false) {
|
||||||
|
// Process the pre-burst section
|
||||||
|
for (int i = 0; i < BURST_START; i++) {
|
||||||
|
out[i] = in[i] * math::phasor(-pcl.phase);
|
||||||
|
pcl.advancePhase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the burst itself
|
||||||
|
if (aphase) {
|
||||||
|
for (int i = BURST_START; i < BURST_END; i++) {
|
||||||
|
complex_t outVal = in[i] * math::phasor(-pcl.phase);
|
||||||
|
out[i] = outVal;
|
||||||
|
pcl.advance(math::normalizePhase(outVal.phase() - A_PHASE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = BURST_START; i < BURST_END; i++) {
|
||||||
|
complex_t outVal = in[i] * math::phasor(-pcl.phase);
|
||||||
|
out[i] = outVal;
|
||||||
|
pcl.advance(math::normalizePhase(outVal.phase() - B_PHASE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Process the post-burst section
|
||||||
|
for (int i = BURST_END; i < count; i++) {
|
||||||
|
out[i] = in[i] * math::phasor(-pcl.phase);
|
||||||
|
pcl.advancePhase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int processBlank(int count, complex_t* in, complex_t* out) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
out[i] = in[i] * math::phasor(-pcl.phase);
|
||||||
|
pcl.advancePhase();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
239
decoder_modules/atv_decoder/src/chrominance_filter.h
Normal file
239
decoder_modules/atv_decoder/src/chrominance_filter.h
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <dsp/types.h>
|
||||||
|
|
||||||
|
inline const dsp::complex_t CHROMA_FIR[] = {
|
||||||
|
{-0.000005461290583903, -0.000011336784355655},
|
||||||
|
{ 0.000020060944485414, 0.000009851315045203},
|
||||||
|
{-0.000034177222729438, 0.000007245841504981},
|
||||||
|
{ 0.000027694034878705, -0.000033114740542635},
|
||||||
|
{-0.000001217597841648, 0.000039141482370942},
|
||||||
|
{-0.000008324593371228, -0.000011315001355976},
|
||||||
|
{-0.000038085228233509, -0.000010585909953738},
|
||||||
|
{ 0.000114833396071141, -0.000047778708840608},
|
||||||
|
{-0.000115428390169113, 0.000205816198882814},
|
||||||
|
{-0.000055467806072871, -0.000356692479491626},
|
||||||
|
{ 0.000349316846854190, 0.000326162940234916},
|
||||||
|
{-0.000558465829929114, -0.000048001521408724},
|
||||||
|
{ 0.000488176200631416, -0.000319593757302922},
|
||||||
|
{-0.000169437838021935, 0.000501610900725908},
|
||||||
|
{-0.000131793335799502, -0.000373003580727547},
|
||||||
|
{ 0.000166817395492786, 0.000105930895534474},
|
||||||
|
{ 0.000030499908326112, -0.000003048682668943},
|
||||||
|
{-0.000174999505027919, 0.000168008090089458},
|
||||||
|
{ 0.000054431163395030, -0.000385174790951272},
|
||||||
|
{ 0.000215876012859739, 0.000372695852521209},
|
||||||
|
{-0.000325534912280750, -0.000130173041693966},
|
||||||
|
{ 0.000154951430569290, -0.000045395998708328},
|
||||||
|
{ 0.000054324657659002, -0.000076028700470037},
|
||||||
|
{ 0.000015664427565764, 0.000348002612845696},
|
||||||
|
{-0.000345943017888332, -0.000402175417043307},
|
||||||
|
{ 0.000568731727879741, 0.000112347863435682},
|
||||||
|
{-0.000416485880859085, 0.000211750352828909},
|
||||||
|
{ 0.000087462353623011, -0.000188197153014309},
|
||||||
|
{-0.000032082305030264, -0.000136804226080664},
|
||||||
|
{ 0.000379089999045955, 0.000303466839685362},
|
||||||
|
{-0.000726760198519770, -0.000007022279302816},
|
||||||
|
{ 0.000619888661818195, -0.000476871323359809},
|
||||||
|
{-0.000151885493742993, 0.000595641190573181},
|
||||||
|
{-0.000100626407015494, -0.000227947144491108},
|
||||||
|
{-0.000201935458823941, -0.000107628631934340},
|
||||||
|
{ 0.000680260922139900, -0.000120771182888852},
|
||||||
|
{-0.000666108629277491, 0.000744775901128973},
|
||||||
|
{ 0.000067236591919755, -0.001044125966364420},
|
||||||
|
{ 0.000447037274751822, 0.000651912509450913},
|
||||||
|
{-0.000262675893448686, -0.000082499729563337},
|
||||||
|
{-0.000349821460486320, 0.000132102793530818},
|
||||||
|
{ 0.000507024815168287, -0.000837598610490618},
|
||||||
|
{ 0.000163814255478652, 0.001346530693477834},
|
||||||
|
{-0.000970457632383793, -0.000968411010101160},
|
||||||
|
{ 0.000974834882891140, 0.000116507082762032},
|
||||||
|
{-0.000225464280571542, 0.000137131865995708},
|
||||||
|
{-0.000211542240694642, 0.000563783548428947},
|
||||||
|
{-0.000414412310798766, -0.001309793399193736},
|
||||||
|
{ 0.001497010004594478, 0.001021907858926259},
|
||||||
|
{-0.001752019159639658, 0.000116536066154131},
|
||||||
|
{ 0.000872822027879430, -0.000783952720205569},
|
||||||
|
{-0.000032439446797970, 0.000184988059956734},
|
||||||
|
{ 0.000446259382722895, 0.000833040920509238},
|
||||||
|
{-0.001741577737284306, -0.000764423771425237},
|
||||||
|
{ 0.002306569133792772, -0.000593352416441601},
|
||||||
|
{-0.001336084746214192, 0.001744394557524181},
|
||||||
|
{-0.000015810020735495, -0.001342809547658260},
|
||||||
|
{ 0.000007636494885364, 0.000009498318627546},
|
||||||
|
{ 0.001403876768349702, 0.000326101441888391},
|
||||||
|
{-0.002351020828600226, 0.001098649819278302},
|
||||||
|
{ 0.001389314639579544, -0.002746943712072884},
|
||||||
|
{ 0.000526319899588909, 0.002635084366837732},
|
||||||
|
{-0.001109526585744687, -0.000950323796527721},
|
||||||
|
{-0.000307792427984886, -0.000013203419520794},
|
||||||
|
{ 0.001737955094951111, -0.001247368808692850},
|
||||||
|
{-0.000974502437588420, 0.003352512117661680},
|
||||||
|
{-0.001462571137390936, -0.003635296917435679},
|
||||||
|
{ 0.002783459090201693, 0.001604420226187745},
|
||||||
|
{-0.001471518558760170, 0.000211117948702137},
|
||||||
|
{-0.000575340825070194, 0.000601820846100026},
|
||||||
|
{ 0.000302090333345692, -0.003088058972305493},
|
||||||
|
{ 0.002496092353182990, 0.003912508340989065},
|
||||||
|
{-0.004645661091012423, -0.001630427298020200},
|
||||||
|
{ 0.003556824805628799, -0.001209822327859352},
|
||||||
|
{-0.000744999556260706, 0.001143238699138109},
|
||||||
|
{ 0.000144278726929409, 0.001638049051599065},
|
||||||
|
{-0.003025291044450178, -0.003226370992887968},
|
||||||
|
{ 0.006047866290490120, 0.000927406808799887},
|
||||||
|
{-0.005338456415106141, 0.003008811999350399},
|
||||||
|
{ 0.001642959659014839, -0.003972384205231079},
|
||||||
|
{ 0.000273874932822212, 0.000977326273749033},
|
||||||
|
{ 0.002315022846573390, 0.001695671268241410},
|
||||||
|
{-0.006240953957978884, 0.000207330368698293},
|
||||||
|
{ 0.006164252120861735, -0.005177351717451013},
|
||||||
|
{-0.001560310257561104, 0.007437030759707700},
|
||||||
|
{-0.002131333814462852, -0.004317129694157112},
|
||||||
|
{ 0.000280518918541908, 0.000134405998842553},
|
||||||
|
{ 0.004612116481180659, -0.001024468120657814},
|
||||||
|
{-0.005599300279638699, 0.006828277067771868},
|
||||||
|
{ 0.000228879728552504, -0.010675998154712657},
|
||||||
|
{ 0.005692081512980654, 0.007582243186569848},
|
||||||
|
{-0.005100500569859509, -0.001364751685737153},
|
||||||
|
{-0.000902490398043454, 0.000385770160220703},
|
||||||
|
{ 0.003673858819546609, -0.006701685283451640},
|
||||||
|
{ 0.002079056046131593, 0.012568579063417429},
|
||||||
|
{-0.010730008156911677, -0.009826454574016218},
|
||||||
|
{ 0.012092401380903161, 0.000921764172237851},
|
||||||
|
{-0.004714530989129091, 0.003151948807627123},
|
||||||
|
{-0.001055930168838909, 0.003228576712467020},
|
||||||
|
{-0.004343270165991213, -0.011924332879354394},
|
||||||
|
{ 0.016499994418955999, 0.010255324919126899},
|
||||||
|
{-0.021047239750251585, 0.002309419513135448},
|
||||||
|
{ 0.011855513874047341, -0.011604071033866310},
|
||||||
|
{-0.000777842281358575, 0.005916341648175263},
|
||||||
|
{ 0.004380939277688377, 0.007397670455730446},
|
||||||
|
{-0.021891594662401131, -0.008509480947490166},
|
||||||
|
{ 0.032787638290674201, -0.009950745850861956},
|
||||||
|
{-0.021022579272463194, 0.030030850567389102},
|
||||||
|
{-0.001508145650189953, -0.027571914870304640},
|
||||||
|
{ 0.004056649693022923, 0.004624901687718579},
|
||||||
|
{ 0.025728742586666287, 0.004824671348397606},
|
||||||
|
{-0.058002700931665603, 0.030198618296813803},
|
||||||
|
{ 0.043631619628438784, -0.096308304333327280},
|
||||||
|
{ 0.033451363423624300, 0.136687079396426990},
|
||||||
|
{-0.129387018420204200, -0.101540513046619400},
|
||||||
|
{ 0.172881344826560730, -0.000000000000005297},
|
||||||
|
{-0.129387018420198010, 0.101540513046627330},
|
||||||
|
{ 0.033451363423615862, -0.136687079396429050},
|
||||||
|
{ 0.043631619628444723, 0.096308304333324601},
|
||||||
|
{-0.058002700931667456, -0.030198618296810247},
|
||||||
|
{ 0.025728742586665992, -0.004824671348399184},
|
||||||
|
{ 0.004056649693022639, -0.004624901687718827},
|
||||||
|
{-0.001508145650188251, 0.027571914870304734},
|
||||||
|
{-0.021022579272465047, -0.030030850567387805},
|
||||||
|
{ 0.032787638290674812, 0.009950745850859947},
|
||||||
|
{-0.021891594662400610, 0.008509480947491507},
|
||||||
|
{ 0.004380939277687923, -0.007397670455730714},
|
||||||
|
{-0.000777842281358940, -0.005916341648175215},
|
||||||
|
{ 0.011855513874048058, 0.011604071033865578},
|
||||||
|
{-0.021047239750251731, -0.002309419513134139},
|
||||||
|
{ 0.016499994418955360, -0.010255324919127926},
|
||||||
|
{-0.004343270165990471, 0.011924332879354665},
|
||||||
|
{-0.001055930168839110, -0.003228576712466955},
|
||||||
|
{-0.004714530989129287, -0.003151948807626830},
|
||||||
|
{ 0.012092401380903103, -0.000921764172238603},
|
||||||
|
{-0.010730008156911072, 0.009826454574016881},
|
||||||
|
{ 0.002079056046130817, -0.012568579063417559},
|
||||||
|
{ 0.003673858819547020, 0.006701685283451416},
|
||||||
|
{-0.000902490398043478, -0.000385770160220647},
|
||||||
|
{-0.005100500569859424, 0.001364751685737466},
|
||||||
|
{ 0.005692081512980187, -0.007582243186570198},
|
||||||
|
{ 0.000228879728553163, 0.010675998154712643},
|
||||||
|
{-0.005599300279639117, -0.006828277067771524},
|
||||||
|
{ 0.004612116481180722, 0.001024468120657532},
|
||||||
|
{ 0.000280518918541900, -0.000134405998842571},
|
||||||
|
{-0.002131333814462586, 0.004317129694157243},
|
||||||
|
{-0.001560310257561563, -0.007437030759707604},
|
||||||
|
{ 0.006164252120862052, 0.005177351717450635},
|
||||||
|
{-0.006240953957978898, -0.000207330368697911},
|
||||||
|
{ 0.002315022846573286, -0.001695671268241552},
|
||||||
|
{ 0.000273874932822152, -0.000977326273749050},
|
||||||
|
{ 0.001642959659015084, 0.003972384205230976},
|
||||||
|
{-0.005338456415106324, -0.003008811999350072},
|
||||||
|
{ 0.006047866290490063, -0.000927406808800258},
|
||||||
|
{-0.003025291044449980, 0.003226370992888153},
|
||||||
|
{ 0.000144278726929308, -0.001638049051599074},
|
||||||
|
{-0.000744999556260777, -0.001143238699138063},
|
||||||
|
{ 0.003556824805628873, 0.001209822327859134},
|
||||||
|
{-0.004645661091012323, 0.001630427298020484},
|
||||||
|
{ 0.002496092353182751, -0.003912508340989219},
|
||||||
|
{ 0.000302090333345882, 0.003088058972305475},
|
||||||
|
{-0.000575340825070231, -0.000601820846099991},
|
||||||
|
{-0.001471518558760183, -0.000211117948702046},
|
||||||
|
{ 0.002783459090201593, -0.001604420226187919},
|
||||||
|
{-0.001462571137390710, 0.003635296917435769},
|
||||||
|
{-0.000974502437588628, -0.003352512117661619},
|
||||||
|
{ 0.001737955094951189, 0.001247368808692742},
|
||||||
|
{-0.000307792427984885, 0.000013203419520814},
|
||||||
|
{-0.001109526585744628, 0.000950323796527789},
|
||||||
|
{ 0.000526319899588746, -0.002635084366837765},
|
||||||
|
{ 0.001389314639579712, 0.002746943712072799},
|
||||||
|
{-0.002351020828600294, -0.001098649819278158},
|
||||||
|
{ 0.001403876768349682, -0.000326101441888477},
|
||||||
|
{ 0.000007636494885364, -0.000009498318627546},
|
||||||
|
{-0.000015810020735412, 0.001342809547658261},
|
||||||
|
{-0.001336084746214299, -0.001744394557524099},
|
||||||
|
{ 0.002306569133792808, 0.000593352416441460},
|
||||||
|
{-0.001741577737284259, 0.000764423771425344},
|
||||||
|
{ 0.000446259382722843, -0.000833040920509266},
|
||||||
|
{-0.000032439446797982, -0.000184988059956732},
|
||||||
|
{ 0.000872822027879478, 0.000783952720205515},
|
||||||
|
{-0.001752019159639665, -0.000116536066154024},
|
||||||
|
{ 0.001497010004594416, -0.001021907858926351},
|
||||||
|
{-0.000414412310798685, 0.001309793399193761},
|
||||||
|
{-0.000211542240694677, -0.000563783548428934},
|
||||||
|
{-0.000225464280571550, -0.000137131865995694},
|
||||||
|
{ 0.000974834882891133, -0.000116507082762092},
|
||||||
|
{-0.000970457632383734, 0.000968411010101219},
|
||||||
|
{ 0.000163814255478569, -0.001346530693477844},
|
||||||
|
{ 0.000507024815168339, 0.000837598610490586},
|
||||||
|
{-0.000349821460486328, -0.000132102793530797},
|
||||||
|
{-0.000262675893448681, 0.000082499729563353},
|
||||||
|
{ 0.000447037274751782, -0.000651912509450940},
|
||||||
|
{ 0.000067236591919819, 0.001044125966364416},
|
||||||
|
{-0.000666108629277537, -0.000744775901128932},
|
||||||
|
{ 0.000680260922139908, 0.000120771182888810},
|
||||||
|
{-0.000201935458823935, 0.000107628631934352},
|
||||||
|
{-0.000100626407015480, 0.000227947144491114},
|
||||||
|
{-0.000151885493743030, -0.000595641190573172},
|
||||||
|
{ 0.000619888661818225, 0.000476871323359771},
|
||||||
|
{-0.000726760198519770, 0.000007022279302861},
|
||||||
|
{ 0.000379089999045936, -0.000303466839685386},
|
||||||
|
{-0.000032082305030256, 0.000136804226080666},
|
||||||
|
{ 0.000087462353623023, 0.000188197153014303},
|
||||||
|
{-0.000416485880859098, -0.000211750352828883},
|
||||||
|
{ 0.000568731727879734, -0.000112347863435717},
|
||||||
|
{-0.000345943017888307, 0.000402175417043329},
|
||||||
|
{ 0.000015664427565742, -0.000348002612845697},
|
||||||
|
{ 0.000054324657659007, 0.000076028700470034},
|
||||||
|
{ 0.000154951430569292, 0.000045395998708319},
|
||||||
|
{-0.000325534912280742, 0.000130173041693986},
|
||||||
|
{ 0.000215876012859716, -0.000372695852521222},
|
||||||
|
{ 0.000054431163395054, 0.000385174790951269},
|
||||||
|
{-0.000174999505027930, -0.000168008090089447},
|
||||||
|
{ 0.000030499908326113, 0.000003048682668941},
|
||||||
|
{ 0.000166817395492779, -0.000105930895534485},
|
||||||
|
{-0.000131793335799479, 0.000373003580727555},
|
||||||
|
{-0.000169437838021966, -0.000501610900725898},
|
||||||
|
{ 0.000488176200631435, 0.000319593757302892},
|
||||||
|
{-0.000558465829929111, 0.000048001521408758},
|
||||||
|
{ 0.000349316846854170, -0.000326162940234938},
|
||||||
|
{-0.000055467806072849, 0.000356692479491629},
|
||||||
|
{-0.000115428390169126, -0.000205816198882806},
|
||||||
|
{ 0.000114833396071144, 0.000047778708840601},
|
||||||
|
{-0.000038085228233508, 0.000010585909953741},
|
||||||
|
{-0.000008324593371228, 0.000011315001355977},
|
||||||
|
{-0.000001217597841650, -0.000039141482370942},
|
||||||
|
{ 0.000027694034878707, 0.000033114740542633},
|
||||||
|
{-0.000034177222729439, -0.000007245841504979},
|
||||||
|
{ 0.000020060944485413, -0.000009851315045204},
|
||||||
|
{-0.000005461290583903, 0.000011336784355656},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHROMA_FIR_SIZE (sizeof(CHROMA_FIR)/sizeof(dsp::complex_t))
|
||||||
|
#define CHROMA_FIR_DELAY ((CHROMA_FIR_SIZE-1)/2)
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <dsp/types.h>
|
|
||||||
|
|
||||||
const dsp::complex_t CHROMA_BANDPASS[123] = {
|
|
||||||
{ -0.000007675039564594f, -0.000017362992335168f },
|
|
||||||
{ 0.000050180791439308f, -0.000005054021864311f },
|
|
||||||
{ -0.000022529111707761f, 0.000102942513429095f },
|
|
||||||
{ -0.000157609487484146f, -0.000092618697641464f },
|
|
||||||
{ 0.000205649042029007f, -0.000181710515677257f },
|
|
||||||
{ 0.000143445458895462f, 0.000331994546004200f },
|
|
||||||
{ -0.000414693079508517f, 0.000038265188132615f },
|
|
||||||
{ 0.000090081630021837f, -0.000395731646002122f },
|
|
||||||
{ 0.000257705918065856f, 0.000154354504676150f },
|
|
||||||
{ -0.000064051192147575f, 0.000055648228186439f },
|
|
||||||
{ 0.000089938060647145f, 0.000213032074676941f },
|
|
||||||
{ -0.000604775098099200f, 0.000050706635726124f },
|
|
||||||
{ 0.000223309865890358f, -0.000944433958755193f },
|
|
||||||
{ 0.001049943574694384f, 0.000640863688898729f },
|
|
||||||
{ -0.000983491651119595f, 0.000840133365053179f },
|
|
||||||
{ -0.000417178588714773f, -0.001011686459999295f },
|
|
||||||
{ 0.000616677332283103f, -0.000046513429902547f },
|
|
||||||
{ 0.000018549463752019f, -0.000075619948809012f },
|
|
||||||
{ 0.000734408386201158f, 0.000456742966201638f },
|
|
||||||
{ -0.001192460562555901f, 0.001001510577200253f },
|
|
||||||
{ -0.000729137747758392f, -0.001811046261815935f },
|
|
||||||
{ 0.001878272869910273f, -0.000125879189667096f },
|
|
||||||
{ -0.000312873903977849f, 0.001230889889574772f },
|
|
||||||
{ -0.000142534831707354f, -0.000090307321579771f },
|
|
||||||
{ -0.000942796972567241f, 0.000778470227412111f },
|
|
||||||
{ -0.000945381510920278f, -0.002406055808135091f },
|
|
||||||
{ 0.003537159230775561f, -0.000207350791625892f },
|
|
||||||
{ -0.000956199555190230f, 0.003634225577771235f },
|
|
||||||
{ -0.002543835202533561f, -0.001641705037372486f },
|
|
||||||
{ 0.001064108471592447f, -0.000863770138941644f },
|
|
||||||
{ -0.000335799601479829f, -0.000876091753216939f },
|
|
||||||
{ 0.003390761989356699f, -0.000170321604912419f },
|
|
||||||
{ -0.001408130728751909f, 0.005175554625981795f },
|
|
||||||
{ -0.005203055300834108f, -0.003419861284250694f },
|
|
||||||
{ 0.004342719678657084f, -0.003465264906764298f },
|
|
||||||
{ 0.001143432997855297f, 0.003059520699490539f },
|
|
||||||
{ 0.000304096484476364f, -0.000012725974706621f },
|
|
||||||
{ -0.001193870642975282f, 0.004247469277548632f },
|
|
||||||
{ -0.006681021498855877f, -0.004471771356204969f },
|
|
||||||
{ 0.007965721969864534f, -0.006247895626072559f },
|
|
||||||
{ 0.003365883969059717f, 0.009241201835481184f },
|
|
||||||
{ -0.006835562188141396f, 0.000228798228738161f },
|
|
||||||
{ 0.000409900284971528f, -0.001412838961851673f },
|
|
||||||
{ -0.004331406608345981f, -0.002951876085350234f },
|
|
||||||
{ 0.009290089917766562f, -0.007161958719089258f },
|
|
||||||
{ 0.005418326020709935f, 0.015272361365960607f },
|
|
||||||
{ -0.017077565432843410f, 0.000428641984774326f },
|
|
||||||
{ 0.003850771342644978f, -0.012869517593577566f },
|
|
||||||
{ 0.004380859690202961f, 0.003039552423897447f },
|
|
||||||
{ 0.004761181766399753f, -0.003607421240356480f },
|
|
||||||
{ 0.005926935731028822f, 0.017160134858844222f },
|
|
||||||
{ -0.028153584885925551f, 0.000471042980325370f },
|
|
||||||
{ 0.009655944938035437f, -0.031314555422639050f },
|
|
||||||
{ 0.023930146568136038f, 0.016901617811072800f },
|
|
||||||
{ -0.012998853255109976f, 0.009678807314399702f },
|
|
||||||
{ 0.002043176559434885f, 0.006079907699564680f },
|
|
||||||
{ -0.036686455817128191f, 0.000306882557812233f },
|
|
||||||
{ 0.021529138474771701f, -0.067800343150283604f },
|
|
||||||
{ 0.085421344938160879f, 0.061409588050754214f },
|
|
||||||
{ -0.108166660998898100f, 0.079141989828113088f },
|
|
||||||
{ -0.047617308971534079f, -0.145721049254261960f },
|
|
||||||
{ 0.160079041453427080f, -0.000000000000000427f },
|
|
||||||
{ -0.047617308971533295f, 0.145721049254262240f },
|
|
||||||
{ -0.108166660998898530f, -0.079141989828112505f },
|
|
||||||
{ 0.085421344938160546f, -0.061409588050754672f },
|
|
||||||
{ 0.021529138474772065f, 0.067800343150283493f },
|
|
||||||
{ -0.036686455817128191f, -0.000306882557812037f },
|
|
||||||
{ 0.002043176559434853f, -0.006079907699564691f },
|
|
||||||
{ -0.012998853255110026f, -0.009678807314399631f },
|
|
||||||
{ 0.023930146568135951f, -0.016901617811072928f },
|
|
||||||
{ 0.009655944938035604f, 0.031314555422638994f },
|
|
||||||
{ -0.028153584885925554f, -0.000471042980325220f },
|
|
||||||
{ 0.005926935731028730f, -0.017160134858844253f },
|
|
||||||
{ 0.004761181766399772f, 0.003607421240356455f },
|
|
||||||
{ 0.004380859690202943f, -0.003039552423897470f },
|
|
||||||
{ 0.003850771342645046f, 0.012869517593577545f },
|
|
||||||
{ -0.017077565432843413f, -0.000428641984774235f },
|
|
||||||
{ 0.005418326020709854f, -0.015272361365960637f },
|
|
||||||
{ 0.009290089917766600f, 0.007161958719089209f },
|
|
||||||
{ -0.004331406608345964f, 0.002951876085350257f },
|
|
||||||
{ 0.000409900284971536f, 0.001412838961851670f },
|
|
||||||
{ -0.006835562188141398f, -0.000228798228738125f },
|
|
||||||
{ 0.003365883969059667f, -0.009241201835481201f },
|
|
||||||
{ 0.007965721969864567f, 0.006247895626072517f },
|
|
||||||
{ -0.006681021498855855f, 0.004471771356205005f },
|
|
||||||
{ -0.001193870642975304f, -0.004247469277548626f },
|
|
||||||
{ 0.000304096484476364f, 0.000012725974706619f },
|
|
||||||
{ 0.001143432997855281f, -0.003059520699490545f },
|
|
||||||
{ 0.004342719678657102f, 0.003465264906764274f },
|
|
||||||
{ -0.005203055300834089f, 0.003419861284250722f },
|
|
||||||
{ -0.001408130728751936f, -0.005175554625981787f },
|
|
||||||
{ 0.003390761989356700f, 0.000170321604912401f },
|
|
||||||
{ -0.000335799601479825f, 0.000876091753216940f },
|
|
||||||
{ 0.001064108471592452f, 0.000863770138941638f },
|
|
||||||
{ -0.002543835202533552f, 0.001641705037372499f },
|
|
||||||
{ -0.000956199555190250f, -0.003634225577771230f },
|
|
||||||
{ 0.003537159230775563f, 0.000207350791625874f },
|
|
||||||
{ -0.000945381510920265f, 0.002406055808135096f },
|
|
||||||
{ -0.000942796972567245f, -0.000778470227412106f },
|
|
||||||
{ -0.000142534831707354f, 0.000090307321579771f },
|
|
||||||
{ -0.000312873903977856f, -0.001230889889574770f },
|
|
||||||
{ 0.001878272869910274f, 0.000125879189667086f },
|
|
||||||
{ -0.000729137747758382f, 0.001811046261815939f },
|
|
||||||
{ -0.001192460562555906f, -0.001001510577200246f },
|
|
||||||
{ 0.000734408386201156f, -0.000456742966201642f },
|
|
||||||
{ 0.000018549463752019f, 0.000075619948809012f },
|
|
||||||
{ 0.000616677332283103f, 0.000046513429902543f },
|
|
||||||
{ -0.000417178588714767f, 0.001011686459999298f },
|
|
||||||
{ -0.000983491651119600f, -0.000840133365053174f },
|
|
||||||
{ 0.001049943574694380f, -0.000640863688898734f },
|
|
||||||
{ 0.000223309865890363f, 0.000944433958755192f },
|
|
||||||
{ -0.000604775098099200f, -0.000050706635726121f },
|
|
||||||
{ 0.000089938060647144f, -0.000213032074676941f },
|
|
||||||
{ -0.000064051192147576f, -0.000055648228186438f },
|
|
||||||
{ 0.000257705918065856f, -0.000154354504676151f },
|
|
||||||
{ 0.000090081630021839f, 0.000395731646002121f },
|
|
||||||
{ -0.000414693079508517f, -0.000038265188132613f },
|
|
||||||
{ 0.000143445458895461f, -0.000331994546004200f },
|
|
||||||
{ 0.000205649042029008f, 0.000181710515677256f },
|
|
||||||
{ -0.000157609487484145f, 0.000092618697641465f },
|
|
||||||
{ -0.000022529111707761f, -0.000102942513429094f },
|
|
||||||
{ 0.000050180791439308f, 0.000005054021864311f },
|
|
||||||
{ -0.000007675039564594f, 0.000017362992335168f }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CHROMA_BANDPASS_SIZE (sizeof(CHROMA_BANDPASS)/sizeof(dsp::complex_t))
|
|
||||||
#define CHROMA_BANDPASS_DELAY (CHROMA_BANDPASS_SIZE/2)
|
|
||||||
@@ -5,33 +5,6 @@
|
|||||||
#include <dsp/multirate/polyphase_bank.h>
|
#include <dsp/multirate/polyphase_bank.h>
|
||||||
#include <dsp/math/step.h>
|
#include <dsp/math/step.h>
|
||||||
|
|
||||||
#define LINE_SIZE 945
|
|
||||||
|
|
||||||
#define SYNC_LEN 70
|
|
||||||
#define SYNC_SIDE_LEN 17
|
|
||||||
#define SYNC_L_START (LINE_SIZE - SYNC_SIDE_LEN)
|
|
||||||
#define SYNC_R_START (SYNC_LEN/2)
|
|
||||||
#define SYNC_R_END (SYNC_R_START + (SYNC_LEN/2) + SYNC_SIDE_LEN)
|
|
||||||
#define SYNC_HALF_LEN ((SYNC_LEN/2) + SYNC_SIDE_LEN)
|
|
||||||
|
|
||||||
#define EQUAL_LEN 35
|
|
||||||
|
|
||||||
#define HBLANK_START SYNC_LEN
|
|
||||||
#define HBLANK_END 155
|
|
||||||
#define HBLANK_LEN (HBLANK_END - HBLANK_START + 1)
|
|
||||||
|
|
||||||
#define SYNC_LEVEL (-0.428)
|
|
||||||
|
|
||||||
#define COLORBURST_START 84
|
|
||||||
#define COLORBURST_LEN 33
|
|
||||||
|
|
||||||
#define MAX_LOCK 1000
|
|
||||||
|
|
||||||
dsp::complex_t PHASE_REF[2] = {
|
|
||||||
{ -0.707106781186547f, 0.707106781186547f },
|
|
||||||
{ -0.707106781186547f, -0.707106781186547f }
|
|
||||||
};
|
|
||||||
|
|
||||||
class LineSync : public dsp::Processor<float, float> {
|
class LineSync : public dsp::Processor<float, float> {
|
||||||
using base_type = dsp::Processor<float, float>;
|
using base_type = dsp::Processor<float, float>;
|
||||||
public:
|
public:
|
||||||
@@ -54,17 +27,41 @@ public:
|
|||||||
_interpPhaseCount = interpPhaseCount;
|
_interpPhaseCount = interpPhaseCount;
|
||||||
_interpTapCount = interpTapCount;
|
_interpTapCount = interpTapCount;
|
||||||
|
|
||||||
|
pcl.init(_muGain, _omegaGain, 0.0, 0.0, 1.0, _omega, _omega * (1.0 - omegaRelLimit), _omega * (1.0 + omegaRelLimit));
|
||||||
generateInterpTaps();
|
generateInterpTaps();
|
||||||
buffer = dsp::buffer::alloc<float>(STREAM_BUFFER_SIZE + _interpTapCount);
|
buffer = dsp::buffer::alloc<float>(STREAM_BUFFER_SIZE + _interpTapCount);
|
||||||
bufStart = &buffer[_interpTapCount - 1];
|
bufStart = &buffer[_interpTapCount - 1];
|
||||||
|
|
||||||
// TODO: Needs tuning, so do the gains
|
|
||||||
maxPeriod = (int32_t)(1.0001 * (float)(1 << 30));
|
|
||||||
minPeriod = (int32_t)(0.9999 * (float)(1 << 30));
|
|
||||||
|
|
||||||
base_type::init(in);
|
base_type::init(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setOmegaGain(double omegaGain) {
|
||||||
|
assert(base_type::_block_init);
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
|
_omegaGain = omegaGain;
|
||||||
|
pcl.setCoefficients(_muGain, _omegaGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMuGain(double muGain) {
|
||||||
|
assert(base_type::_block_init);
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
|
_muGain = muGain;
|
||||||
|
pcl.setCoefficients(_muGain, _omegaGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOmegaRelLimit(double omegaRelLimit) {
|
||||||
|
assert(base_type::_block_init);
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
|
_omegaRelLimit = omegaRelLimit;
|
||||||
|
pcl.setFreqLimits(_omega * (1.0 - _omegaRelLimit), _omega * (1.0 + _omegaRelLimit));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSyncLevel(float level) {
|
||||||
|
assert(base_type::_block_init);
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
|
syncLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
void setInterpParams(int interpPhaseCount, int interpTapCount) {
|
void setInterpParams(int interpPhaseCount, int interpTapCount) {
|
||||||
assert(base_type::_block_init);
|
assert(base_type::_block_init);
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
@@ -84,7 +81,8 @@ public:
|
|||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
||||||
base_type::tempStop();
|
base_type::tempStop();
|
||||||
offset = 0;
|
offset = 0;
|
||||||
phase = 0;
|
pcl.phase = 0.0f;
|
||||||
|
pcl.freq = _omega;
|
||||||
base_type::tempStart();
|
base_type::tempStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,120 +93,61 @@ public:
|
|||||||
// Copy data to work buffer
|
// Copy data to work buffer
|
||||||
memcpy(bufStart, base_type::_in->readBuf, count * sizeof(float));
|
memcpy(bufStart, base_type::_in->readBuf, count * sizeof(float));
|
||||||
|
|
||||||
// Process samples while they are available
|
if (test2) {
|
||||||
|
test2 = false;
|
||||||
|
offset += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all samples
|
||||||
while (offset < count) {
|
while (offset < count) {
|
||||||
// While the offset is negative, out put zeros
|
// Calculate new output value
|
||||||
while (offset < 0 && pixel < LINE_SIZE) {
|
int phase = std::clamp<int>(floorf(pcl.phase * (float)_interpPhaseCount), 0, _interpPhaseCount - 1);
|
||||||
// Output a zero
|
float outVal;
|
||||||
base_type::out.writeBuf[pixel++] = 0.0f;
|
volk_32f_x2_dot_prod_32f(&outVal, &buffer[offset], interpBank.phases[phase], _interpTapCount);
|
||||||
|
base_type::out.writeBuf[outCount++] = outVal;
|
||||||
|
|
||||||
// Increment the phase
|
// If the end of the line is reached, process it and determin error
|
||||||
phase += period;
|
float error = 0;
|
||||||
offset += (phase >> 30);
|
if (outCount >= 720) {
|
||||||
phase &= 0x3FFFFFFF;
|
// Compute averages.
|
||||||
}
|
|
||||||
|
|
||||||
// Process as much of a line as possible
|
|
||||||
while (offset < count && pixel < LINE_SIZE) {
|
|
||||||
// Compute the output sample
|
|
||||||
volk_32f_x2_dot_prod_32f(&base_type::out.writeBuf[pixel++], &buffer[offset], interpBank.phases[(phase >> 23) & 0x7F], _interpTapCount);
|
|
||||||
|
|
||||||
// Increment the phase
|
|
||||||
phase += period;
|
|
||||||
offset += (phase >> 30);
|
|
||||||
phase &= 0x3FFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the line is done, process it
|
|
||||||
if (pixel == LINE_SIZE) {
|
|
||||||
// Compute averages. (TODO: Try faster method)
|
|
||||||
float left = 0.0f, right = 0.0f;
|
float left = 0.0f, right = 0.0f;
|
||||||
int lc = 0, rc = 0;
|
for (int i = (720-17); i < 720; i++) {
|
||||||
for (int i = SYNC_L_START; i < LINE_SIZE; i++) {
|
|
||||||
left += base_type::out.writeBuf[i];
|
left += base_type::out.writeBuf[i];
|
||||||
lc++;
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < SYNC_R_START; i++) {
|
for (int i = 0; i < 27; i++) {
|
||||||
left += base_type::out.writeBuf[i];
|
left += base_type::out.writeBuf[i];
|
||||||
lc++;
|
|
||||||
}
|
}
|
||||||
for (int i = SYNC_R_START; i < SYNC_R_END; i++) {
|
for (int i = 27; i < (54+17); i++) {
|
||||||
right += base_type::out.writeBuf[i];
|
right += base_type::out.writeBuf[i];
|
||||||
rc++;
|
|
||||||
}
|
}
|
||||||
|
left *= (1.0f/44.0f);
|
||||||
|
right *= (1.0f/44.0f);
|
||||||
|
|
||||||
// Compute the error
|
// If the sync is present, compute error
|
||||||
float error = (left - right) * (1.0f/((float)SYNC_HALF_LEN));
|
if ((left < syncLevel && right < syncLevel) && !forceLock) {
|
||||||
|
error = (left + syncBias - right);
|
||||||
// Compute the change in phase and frequency due to the error
|
locked = true;
|
||||||
float periodDelta = error * _omegaGain;
|
|
||||||
float phaseDelta = error * _muGain;
|
|
||||||
|
|
||||||
// Normalize the phase delta (TODO: Make faster)
|
|
||||||
while (phaseDelta <= -1.0f) {
|
|
||||||
phaseDelta += 1.0f;
|
|
||||||
offset--;
|
|
||||||
}
|
|
||||||
while (phaseDelta >= 1.0f) {
|
|
||||||
phaseDelta -= 1.0f;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the period (TODO: Clamp error*omegaGain to prevent weird shit with corrupt samples)
|
|
||||||
period += (int32_t)(periodDelta * (float)(1 << 30));
|
|
||||||
period = std::clamp<uint32_t>(period, minPeriod, maxPeriod);
|
|
||||||
|
|
||||||
// Update the phase
|
|
||||||
phase += (int32_t)(phaseDelta * (float)(1 << 30));
|
|
||||||
|
|
||||||
// Normalize the phase
|
|
||||||
uint32_t overflow = phase >> 30;
|
|
||||||
if (overflow) {
|
|
||||||
if (error < 0) {
|
|
||||||
offset -= 4 - overflow;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
offset += overflow;
|
locked = false;
|
||||||
}
|
|
||||||
}
|
|
||||||
phase &= 0x3FFFFFFF;
|
|
||||||
|
|
||||||
// Find the lowest value
|
|
||||||
float lowest = INFINITY;
|
|
||||||
int lowestId = -1;
|
|
||||||
for (int i = 0; i < LINE_SIZE; i++) {
|
|
||||||
float val = base_type::out.writeBuf[i];
|
|
||||||
if (val < lowest) {
|
|
||||||
lowest = val;
|
|
||||||
lowestId = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the the line is in lock
|
if (++counter >= 100) {
|
||||||
bool lineLocked = (lowestId < SYNC_R_END || lowestId >= SYNC_L_START);
|
counter = 0;
|
||||||
|
//flog::warn("Left: {}, Right: {}, Error: {}, Freq: {}, Phase: {}", left, right, error, pcl.freq, pcl.phase);
|
||||||
// Update the lock status based on the line lock
|
|
||||||
if (!lineLocked && locked) {
|
|
||||||
locked--;
|
|
||||||
}
|
|
||||||
else if (lineLocked && locked < MAX_LOCK) {
|
|
||||||
locked++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not locked, attempt to lock by forcing the sync to happen at the right spot
|
|
||||||
// TODO: This triggers waaaay too easily at low SNR
|
|
||||||
if (!locked && fastLock) {
|
|
||||||
offset += lowestId - SYNC_R_START;
|
|
||||||
locked = MAX_LOCK / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output line
|
// Output line
|
||||||
if (!base_type::out.swap(LINE_SIZE)) { break; }
|
if (!base_type::out.swap(outCount)) { break; }
|
||||||
pixel = 0;
|
outCount = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the offset ready for the next buffer
|
// Advance symbol offset and phase
|
||||||
|
pcl.advance(error);
|
||||||
|
float delta = floorf(pcl.phase);
|
||||||
|
offset += delta;
|
||||||
|
pcl.phase -= delta;
|
||||||
|
}
|
||||||
offset -= count;
|
offset -= count;
|
||||||
|
|
||||||
// Update delay buffer
|
// Update delay buffer
|
||||||
@@ -216,15 +155,16 @@ public:
|
|||||||
|
|
||||||
// Swap if some data was generated
|
// Swap if some data was generated
|
||||||
base_type::_in->flush();
|
base_type::_in->flush();
|
||||||
return 0;
|
return outCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
float syncBias = 0;
|
bool locked = false;
|
||||||
|
bool test2 = false;
|
||||||
|
|
||||||
uint32_t period = (0x800072F3 >> 1);//(1 << 31) + 1;
|
float syncBias = 0.0f;
|
||||||
|
bool forceLock = false;
|
||||||
|
|
||||||
int locked = 0;
|
int counter = 0;
|
||||||
bool fastLock = true;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void generateInterpTaps() {
|
void generateInterpTaps() {
|
||||||
@@ -235,6 +175,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
dsp::multirate::PolyphaseBank<float> interpBank;
|
dsp::multirate::PolyphaseBank<float> interpBank;
|
||||||
|
dsp::loop::PhaseControlLoop<double, false> pcl;
|
||||||
|
|
||||||
double _omega;
|
double _omega;
|
||||||
double _omegaGain;
|
double _omegaGain;
|
||||||
@@ -242,14 +183,11 @@ protected:
|
|||||||
double _omegaRelLimit;
|
double _omegaRelLimit;
|
||||||
int _interpPhaseCount;
|
int _interpPhaseCount;
|
||||||
int _interpTapCount;
|
int _interpTapCount;
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
int outCount = 0;
|
||||||
float* buffer;
|
float* buffer;
|
||||||
float* bufStart;
|
float* bufStart;
|
||||||
|
|
||||||
uint32_t phase = 0;
|
|
||||||
uint32_t maxPeriod;
|
|
||||||
uint32_t minPeriod;
|
|
||||||
float syncLevel = -0.03f;
|
float syncLevel = -0.03f;
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
int pixel = 0;
|
|
||||||
};
|
};
|
||||||
@@ -16,13 +16,9 @@
|
|||||||
#include <dsp/filter/fir.h>
|
#include <dsp/filter/fir.h>
|
||||||
#include <dsp/taps/from_array.h>
|
#include <dsp/taps/from_array.h>
|
||||||
|
|
||||||
#include "amplitude.h"
|
#include "chrominance_filter.h"
|
||||||
#include <dsp/demod/am.h>
|
|
||||||
#include <dsp/loop/fast_agc.h>
|
|
||||||
|
|
||||||
#include "filters.h"
|
#include "chroma_pll.h"
|
||||||
#include <dsp/math/normalize_phase.h>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||||
|
|
||||||
@@ -33,25 +29,24 @@ SDRPP_MOD_INFO{/* Name: */ "atv_decoder",
|
|||||||
/* Max instances */ -1
|
/* Max instances */ -1
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SAMPLE_RATE (625.0f * (float)LINE_SIZE * 25.0f)
|
#define SAMPLE_RATE (625.0f * 720.0f * 25.0f)
|
||||||
|
|
||||||
class ATVDecoderModule : public ModuleManager::Instance {
|
class ATVDecoderModule : public ModuleManager::Instance {
|
||||||
public:
|
public:
|
||||||
ATVDecoderModule(std::string name) : img(768, 576) {
|
ATVDecoderModule(std::string name) : img(720, 625) {
|
||||||
this->name = name;
|
this->name = name;
|
||||||
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 7000000.0f, SAMPLE_RATE, SAMPLE_RATE, SAMPLE_RATE, true);
|
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 8000000.0f, SAMPLE_RATE, SAMPLE_RATE, SAMPLE_RATE, true);
|
||||||
|
|
||||||
agc.init(vfo->output, 1.0f, 1e6, 0.001f, 1.0f);
|
demod.init(vfo->output, SAMPLE_RATE, SAMPLE_RATE / 2.0f);
|
||||||
demod.init(&agc.out, SAMPLE_RATE, SAMPLE_RATE / 2.0f);
|
|
||||||
// demod.init(vfo->output, dsp::demod::AM<float>::CARRIER, 8000000.0f, 50.0 / SAMPLE_RATE, 50.0 / SAMPLE_RATE, 0.0f, SAMPLE_RATE);
|
|
||||||
// demod.init(vfo->output, SAMPLE_RATE, SAMPLE_RATE / 2.0f);
|
|
||||||
sync.init(&demod.out, 1.0f, 1e-6, 1.0, 0.05);
|
sync.init(&demod.out, 1.0f, 1e-6, 1.0, 0.05);
|
||||||
sink.init(&sync.out, handler, this);
|
sink.init(&sync.out, handler, this);
|
||||||
|
|
||||||
r2c.init(NULL);
|
r2c.init(NULL);
|
||||||
|
chromaTaps = dsp::taps::fromArray(CHROMA_FIR_SIZE, CHROMA_FIR);
|
||||||
|
fir.init(NULL, chromaTaps);
|
||||||
|
pll.init(NULL, 0.01, 0.0, dsp::math::hzToRads(4433618.75, SAMPLE_RATE), dsp::math::hzToRads(4433618.75*0.90, SAMPLE_RATE), dsp::math::hzToRads(4433618.75*1.1, SAMPLE_RATE));
|
||||||
|
|
||||||
agc.start();
|
|
||||||
demod.start();
|
demod.start();
|
||||||
sync.start();
|
sync.start();
|
||||||
sink.start();
|
sink.start();
|
||||||
@@ -63,10 +58,7 @@ class ATVDecoderModule : public ModuleManager::Instance {
|
|||||||
if (vfo) {
|
if (vfo) {
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
sigpath::vfoManager.deleteVFO(vfo);
|
||||||
}
|
}
|
||||||
agc.stop();
|
|
||||||
demod.stop();
|
demod.stop();
|
||||||
sync.stop();
|
|
||||||
sink.stop();
|
|
||||||
gui::menu.removeEntry(name);
|
gui::menu.removeEntry(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,218 +82,142 @@ class ATVDecoderModule : public ModuleManager::Instance {
|
|||||||
style::beginDisabled();
|
style::beginDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ideal width for testing: 750pixels
|
||||||
|
|
||||||
ImGui::FillWidth();
|
ImGui::FillWidth();
|
||||||
_this->img.draw();
|
_this->img.draw();
|
||||||
|
|
||||||
ImGui::TextUnformatted("Horizontal Sync:");
|
ImGui::LeftLabel("Sync");
|
||||||
ImGui::SameLine();
|
ImGui::FillWidth();
|
||||||
if (_this->sync.locked > 750) {
|
ImGui::SliderFloat("##syncLvl", &_this->sync_level, -2, 2);
|
||||||
|
|
||||||
|
ImGui::LeftLabel("Min");
|
||||||
|
ImGui::FillWidth();
|
||||||
|
ImGui::SliderFloat("##minLvl", &_this->minLvl, -1.0, 1.0);
|
||||||
|
|
||||||
|
ImGui::LeftLabel("Span");
|
||||||
|
ImGui::FillWidth();
|
||||||
|
ImGui::SliderFloat("##spanLvl", &_this->spanLvl, 0, 1.0);
|
||||||
|
|
||||||
|
ImGui::LeftLabel("Sync Bias");
|
||||||
|
ImGui::FillWidth();
|
||||||
|
ImGui::SliderFloat("##syncBias", &_this->sync.syncBias,-0.1, 0.1);
|
||||||
|
|
||||||
|
if (ImGui::Button("Test2")) {
|
||||||
|
_this->sync.test2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button("Switch frame")) {
|
||||||
|
std::lock_guard<std::mutex> lck(_this->evenFrameMtx);
|
||||||
|
_this->evenFrame = !_this->evenFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_this->sync.locked) {
|
||||||
ImGui::TextColored(ImVec4(0, 1, 0, 1), "Locked");
|
ImGui::TextColored(ImVec4(0, 1, 0, 1), "Locked");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImGui::TextUnformatted("Not locked");
|
ImGui::TextUnformatted("Not locked");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TextUnformatted("Vertical Sync:");
|
ImGui::Checkbox("Force Lock", &_this->sync.forceLock);
|
||||||
ImGui::SameLine();
|
|
||||||
if (_this->vlock > 15) {
|
|
||||||
ImGui::TextColored(ImVec4(0, 1, 0, 1), "Locked");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ImGui::TextUnformatted("Not locked");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Checkbox("Fast Lock", &_this->sync.fastLock);
|
|
||||||
ImGui::Checkbox("Color Mode", &_this->colorMode);
|
|
||||||
|
|
||||||
if (!_this->enabled) {
|
if (!_this->enabled) {
|
||||||
style::endDisabled();
|
style::endDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("Gain: %f", _this->gain);
|
|
||||||
ImGui::Text("Offset: %f", _this->offset);
|
|
||||||
ImGui::Text("Subcarrier: %f", _this->subcarrierFreq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pp = 0;
|
|
||||||
|
|
||||||
static void handler(float *data, int count, void *ctx) {
|
static void handler(float *data, int count, void *ctx) {
|
||||||
ATVDecoderModule *_this = (ATVDecoderModule *)ctx;
|
ATVDecoderModule *_this = (ATVDecoderModule *)ctx;
|
||||||
|
|
||||||
// Correct the offset
|
// Convert line to complex
|
||||||
#if VOLK_VERSION_MAJOR > 2 || (VOLK_VERSION_MAJOR == 2 && VOLK_VERSION_MINOR >= 3)
|
_this->r2c.process(720, data, _this->r2c.out.writeBuf);
|
||||||
volk_32f_s32f_add_32f(data, data, _this->offset, count);
|
|
||||||
#else
|
// Isolate the chroma subcarrier
|
||||||
const float ofs = _this->offset;
|
_this->fir.process(720, _this->r2c.out.writeBuf, _this->fir.out.writeBuf);
|
||||||
|
|
||||||
|
// Run chroma carrier through the PLL
|
||||||
|
_this->pll.process(720, _this->fir.out.writeBuf, _this->pll.out.writeBuf, ((_this->ypos%2)==1) ^ _this->evenFrame);
|
||||||
|
|
||||||
|
// Render line to the image without color
|
||||||
|
int lypos = _this->ypos - 1;
|
||||||
|
if (lypos < 0) { lypos = 624; }
|
||||||
|
uint32_t* lastLine = &((uint32_t *)_this->img.buffer)[(lypos < 313) ? (lypos*720*2) : ((((lypos - 313)*2)+1)*720) ];
|
||||||
|
uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[(_this->ypos < 313) ? (_this->ypos*720*2) : ((((_this->ypos - 313)*2)+1)*720) ];
|
||||||
|
|
||||||
|
//uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[_this->ypos*720];
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
data[i] += ofs;
|
int imval = std::clamp<float>((data[i] - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
|
||||||
}
|
// uint32_t re = std::clamp<float>((_this->pll.out.writeBuf[i].re - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
|
||||||
#endif
|
// uint32_t im = std::clamp<float>((_this->pll.out.writeBuf[i].im - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
|
||||||
|
// currentLine[i] = 0xFF000000 | (im << 8) | re;
|
||||||
// Correct the gain
|
currentLine[i] = 0xFF000000 | (imval << 16) | (imval << 8) | imval;
|
||||||
volk_32f_s32f_multiply_32f(data, data, _this->gain, count);
|
|
||||||
|
|
||||||
// Compute the sync levels
|
|
||||||
float syncLLevel = 0.0f;
|
|
||||||
float syncRLevel = 0.0f;
|
|
||||||
volk_32f_accumulator_s32f(&syncLLevel, data, EQUAL_LEN);
|
|
||||||
volk_32f_accumulator_s32f(&syncRLevel, &data[EQUAL_LEN], SYNC_LEN - EQUAL_LEN);
|
|
||||||
syncLLevel *= 1.0f / EQUAL_LEN;
|
|
||||||
syncRLevel *= 1.0f / (SYNC_LEN - EQUAL_LEN);
|
|
||||||
float syncLevel = (syncLLevel + syncRLevel) * 0.5f; // TODO: It's technically correct but if the sizes were different it wouldn't be
|
|
||||||
|
|
||||||
// Compute the blanking level
|
|
||||||
float blankLevel = 0.0f;
|
|
||||||
volk_32f_accumulator_s32f(&blankLevel, &data[HBLANK_START], HBLANK_LEN);
|
|
||||||
blankLevel /= (float)HBLANK_LEN;
|
|
||||||
|
|
||||||
// Run the offset control loop
|
|
||||||
_this->offset -= (blankLevel / _this->gain)*0.001;
|
|
||||||
_this->offset = std::clamp<float>(_this->offset, -1.0f, 1.0f);
|
|
||||||
_this->gain -= (blankLevel - syncLevel + SYNC_LEVEL)*0.01f;
|
|
||||||
_this->gain = std::clamp<float>(_this->gain, 0.1f, 10.0f);
|
|
||||||
|
|
||||||
// Detect the sync type
|
|
||||||
uint16_t shortSync = (syncLLevel < 0.5f*SYNC_LEVEL) && (syncRLevel > 0.5f*SYNC_LEVEL) && (blankLevel > 0.5f*SYNC_LEVEL);
|
|
||||||
uint16_t longSync = (syncLLevel < 0.5f*SYNC_LEVEL) && (syncRLevel < 0.5f*SYNC_LEVEL) && (blankLevel < 0.5f*SYNC_LEVEL);
|
|
||||||
|
|
||||||
// Save sync type to history
|
|
||||||
_this->syncHistory = (_this->syncHistory << 2) | (longSync << 1) | shortSync;
|
|
||||||
|
|
||||||
// // If the line has a colorburst, decode it
|
|
||||||
// dsp::complex_t* buf1 = _this->r2c.out.readBuf;
|
|
||||||
// dsp::complex_t* buf2 = _this->r2c.out.writeBuf;
|
|
||||||
// if (true) {
|
|
||||||
// // Convert the line into complex
|
|
||||||
// _this->r2c.process(count, data, buf1);
|
|
||||||
|
|
||||||
// // Extract the chroma subcarrier (TODO: Optimise by running only where needed)
|
|
||||||
// for (int i = COLORBURST_START; i < count-(CHROMA_BANDPASS_DELAY+1); i++) {
|
|
||||||
// volk_32fc_x2_dot_prod_32fc((lv_32fc_t*)&buf2[i], (lv_32fc_t*)&buf1[i - CHROMA_BANDPASS_DELAY], (lv_32fc_t*)CHROMA_BANDPASS, CHROMA_BANDPASS_SIZE);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Down convert the chroma subcarrier (TODO: Optimise by running only where needed)
|
|
||||||
// lv_32fc_t startPhase = { 1.0f, 0.0f };
|
|
||||||
// lv_32fc_t phaseDelta = { sinf(_this->subcarrierFreq), cosf(_this->subcarrierFreq) };
|
|
||||||
// #if VOLK_VERSION >= 030100
|
|
||||||
// volk_32fc_s32fc_x2_rotator2_32fc((lv_32fc_t*)&buf2[COLORBURST_START], (lv_32fc_t*)&buf2[COLORBURST_START], &phaseDelta, &startPhase, count - COLORBURST_START);
|
|
||||||
// #else
|
|
||||||
// volk_32fc_s32fc_x2_rotator_32fc((lv_32fc_t*)&buf2[COLORBURST_START], (lv_32fc_t*)&buf2[COLORBURST_START], phaseDelta, &startPhase, count - COLORBURST_START);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// // Compute the phase of the burst
|
|
||||||
// dsp::complex_t burstAvg = { 0.0f, 0.0f };
|
|
||||||
// volk_32fc_accumulator_s32fc((lv_32fc_t*)&burstAvg, (lv_32fc_t*)&buf2[COLORBURST_START], COLORBURST_LEN);
|
|
||||||
// float burstAmp = burstAvg.amplitude();
|
|
||||||
// if (burstAmp*(1.0f/(float)COLORBURST_LEN) < 0.02f) {
|
|
||||||
// printf("%d\n", _this->line);
|
|
||||||
// }
|
|
||||||
// burstAvg *= (1.0f / (burstAmp*burstAmp));
|
|
||||||
// burstAvg = burstAvg.conj();
|
|
||||||
|
|
||||||
// // Normalize the chroma data (TODO: Optimise by running only where needed)
|
|
||||||
// volk_32fc_s32fc_multiply_32fc((lv_32fc_t*)&buf2[COLORBURST_START], (lv_32fc_t*)&buf2[COLORBURST_START], *((lv_32fc_t*)&burstAvg), count - COLORBURST_START);
|
|
||||||
|
|
||||||
// // Compute the frequency error of the burst
|
|
||||||
// float phase = buf2[COLORBURST_START].phase();
|
|
||||||
// float error = 0.0f;
|
|
||||||
// for (int i = COLORBURST_START+1; i < COLORBURST_START+COLORBURST_LEN; i++) {
|
|
||||||
// float cphase = buf2[i].phase();
|
|
||||||
// error += dsp::math::normalizePhase(cphase - phase);
|
|
||||||
// phase = cphase;
|
|
||||||
// }
|
|
||||||
// error *= (1.0f / (float)(COLORBURST_LEN-1));
|
|
||||||
|
|
||||||
// // Update the subcarrier freq
|
|
||||||
// _this->subcarrierFreq += error*0.0001f;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Render the line if it's visible
|
|
||||||
if (_this->ypos >= 34 && _this->ypos <= 34+576-1) {
|
|
||||||
uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[(_this->ypos - 34)*768];
|
|
||||||
if (_this->colorMode) {
|
|
||||||
// for (int i = 155; i < (155+768); i++) {
|
|
||||||
// int imval1 = std::clamp<float>(fabsf(buf2[i-155+COLORBURST_START].re*5.0f) * 255.0f, 0, 255);
|
|
||||||
// int imval2 = std::clamp<float>(fabsf(buf2[i-155+COLORBURST_START].im*5.0f) * 255.0f, 0, 255);
|
|
||||||
// currentLine[i-155] = 0xFF000000 | (imval2 << 8) | imval1;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int i = 155; i < (155+768); i++) {
|
|
||||||
int imval = std::clamp<float>(data[i] * 255.0f, 0, 255);
|
|
||||||
currentLine[i-155] = 0xFF000000 | (imval << 16) | (imval << 8) | imval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute whether to rollover
|
// Vertical scan logic
|
||||||
bool rollToOdd = (_this->ypos == 624);
|
_this->ypos++;
|
||||||
bool rollToEven = (_this->ypos == 623);
|
bool rollover = _this->ypos >= 625;
|
||||||
|
if (rollover) {
|
||||||
// Compute the field sync
|
{
|
||||||
bool syncToOdd = (_this->syncHistory == 0b0101011010010101);
|
std::lock_guard<std::mutex> lck(_this->evenFrameMtx);
|
||||||
bool syncToEven = (_this->syncHistory == 0b0001011010100101);
|
_this->evenFrame = !_this->evenFrame;
|
||||||
|
|
||||||
// Process the sync (NOTE: should start with 0b01, but for some reason I don't see a sync?)
|
|
||||||
if (rollToOdd || syncToOdd) {
|
|
||||||
// Update the vertical lock state
|
|
||||||
bool disagree = (rollToOdd ^ syncToOdd);
|
|
||||||
if (disagree && _this->vlock > 0) {
|
|
||||||
_this->vlock--;
|
|
||||||
}
|
}
|
||||||
else if (!disagree && _this->vlock < 20) {
|
|
||||||
_this->vlock++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the odd field
|
|
||||||
_this->ypos = 1;
|
|
||||||
_this->line++;
|
|
||||||
}
|
|
||||||
else if (rollToEven || syncToEven) {
|
|
||||||
// Update the vertical lock state
|
|
||||||
bool disagree = (rollToEven ^ syncToEven);
|
|
||||||
if (disagree && _this->vlock > 0) {
|
|
||||||
_this->vlock--;
|
|
||||||
}
|
|
||||||
else if (!disagree && _this->vlock < 20) {
|
|
||||||
_this->vlock++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the even field
|
|
||||||
_this->ypos = 0;
|
_this->ypos = 0;
|
||||||
_this->line = 0;
|
|
||||||
|
|
||||||
// Swap the video buffer
|
|
||||||
_this->img.swap();
|
_this->img.swap();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
_this->ypos += 2;
|
|
||||||
_this->line++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NEW SYNC:
|
// Measure vsync levels
|
||||||
float offset = 0.0f;
|
float sync0 = 0.0f, sync1 = 0.0f;
|
||||||
float gain = 1.0f;
|
for (int i = 0; i < 306; i++) {
|
||||||
uint16_t syncHistory = 0;
|
sync0 += data[i];
|
||||||
int line = 0;
|
}
|
||||||
int ypos = 0;
|
for (int i = (720/2); i < ((720/2)+306); i++) {
|
||||||
int vlock = 0;
|
sync1 += data[i];
|
||||||
float subcarrierFreq = 0.0f;
|
}
|
||||||
|
sync0 *= (1.0f/305.0f);
|
||||||
|
sync1 *= (1.0f/305.0f);
|
||||||
|
|
||||||
|
// Save sync detection to history
|
||||||
|
_this->syncHistory >>= 2;
|
||||||
|
_this->syncHistory |= (((uint16_t)(sync1 < _this->sync_level)) << 9) | (((uint16_t)(sync0 < _this->sync_level)) << 8);
|
||||||
|
|
||||||
|
// Trigger vsync in case one is detected
|
||||||
|
// TODO: Also sync with odd field
|
||||||
|
if (!rollover && _this->syncHistory == 0b0000011111) {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lck(_this->evenFrameMtx);
|
||||||
|
_this->evenFrame = !_this->evenFrame;
|
||||||
|
}
|
||||||
|
_this->ypos = 0;
|
||||||
|
_this->img.swap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
|
||||||
VFOManager::VFO *vfo = NULL;
|
VFOManager::VFO *vfo = NULL;
|
||||||
// dsp::demod::Quadrature demod;
|
dsp::demod::Quadrature demod;
|
||||||
dsp::loop::FastAGC<dsp::complex_t> agc;
|
|
||||||
dsp::demod::Amplitude demod;
|
|
||||||
//dsp::demod::AM<float> demod;
|
|
||||||
LineSync sync;
|
LineSync sync;
|
||||||
dsp::sink::Handler<float> sink;
|
dsp::sink::Handler<float> sink;
|
||||||
dsp::convert::RealToComplex r2c;
|
dsp::convert::RealToComplex r2c;
|
||||||
|
dsp::tap<dsp::complex_t> chromaTaps;
|
||||||
|
dsp::filter::FIR<dsp::complex_t, dsp::complex_t> fir;
|
||||||
|
dsp::loop::ChromaPLL pll;
|
||||||
|
int ypos = 0;
|
||||||
|
|
||||||
bool colorMode = false;
|
bool evenFrame = false;
|
||||||
|
std::mutex evenFrameMtx;
|
||||||
|
|
||||||
|
float sync_level = -0.06f;
|
||||||
|
int sync_count = 0;
|
||||||
|
int short_sync = 0;
|
||||||
|
|
||||||
|
float minLvl = 0.0f;
|
||||||
|
float spanLvl = 1.0f;
|
||||||
|
|
||||||
|
bool lockedLines = 0;
|
||||||
|
uint16_t syncHistory = 0;
|
||||||
|
|
||||||
ImGui::ImageDisplay img;
|
ImGui::ImageDisplay img;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
|
||||||
project(dab_decoder)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c")
|
|
||||||
|
|
||||||
include(${SDRPP_MODULE_CMAKE})
|
|
||||||
|
|
||||||
target_include_directories(dab_decoder PRIVATE "src/")
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
# Lib path
|
|
||||||
target_include_directories(dab_decoder PRIVATE "C:/Program Files/codec2/include/")
|
|
||||||
target_link_directories(dab_decoder PRIVATE "C:/Program Files/codec2/lib")
|
|
||||||
|
|
||||||
target_link_libraries(dab_decoder PRIVATE libcodec2)
|
|
||||||
elseif (ANDROID)
|
|
||||||
target_include_directories(dab_decoder PUBLIC
|
|
||||||
/sdr-kit/${ANDROID_ABI}/include/codec2
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(dab_decoder PUBLIC
|
|
||||||
/sdr-kit/${ANDROID_ABI}/lib/libcodec2.so
|
|
||||||
)
|
|
||||||
else ()
|
|
||||||
find_package(PkgConfig)
|
|
||||||
|
|
||||||
pkg_check_modules(LIBCODEC2 REQUIRED codec2)
|
|
||||||
|
|
||||||
target_include_directories(dab_decoder PRIVATE ${LIBCODEC2_INCLUDE_DIRS})
|
|
||||||
target_link_directories(dab_decoder PRIVATE ${LIBCODEC2_LIBRARY_DIRS})
|
|
||||||
target_link_libraries(dab_decoder PRIVATE ${LIBCODEC2_LIBRARIES})
|
|
||||||
|
|
||||||
# Include it because for some reason pkgconfig doesn't look here?
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
|
||||||
target_include_directories(dab_decoder PRIVATE "/usr/local/include")
|
|
||||||
endif()
|
|
||||||
endif ()
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <dsp/processor.h>
|
|
||||||
#include <utils/flog.h>
|
|
||||||
#include <fftw3.h>
|
|
||||||
#include "dab_phase_sym.h"
|
|
||||||
|
|
||||||
namespace dab {
|
|
||||||
class CyclicSync : public dsp::Processor<dsp::complex_t, dsp::complex_t> {
|
|
||||||
using base_type = dsp::Processor<dsp::complex_t, dsp::complex_t>;
|
|
||||||
public:
|
|
||||||
CyclicSync() {}
|
|
||||||
|
|
||||||
// TODO: The default AGC rate is probably way too fast, plot out the avgCorr to see how much it moves
|
|
||||||
CyclicSync(dsp::stream<dsp::complex_t>* in, double symbolLength, double cyclicPrefixLength, double samplerate, float agcRate = 1e-3) { init(in, symbolLength, cyclicPrefixLength, samplerate, agcRate); }
|
|
||||||
|
|
||||||
void init(dsp::stream<dsp::complex_t>* in, double symbolLength, double cyclicPrefixLength, double samplerate, float agcRate = 1e-3) {
|
|
||||||
// Computer the number of samples for the symbol and its cyclic prefix
|
|
||||||
symbolSamps = round(samplerate * symbolLength);
|
|
||||||
prefixSamps = round(samplerate * cyclicPrefixLength);
|
|
||||||
|
|
||||||
// Allocate and clear the delay buffer
|
|
||||||
delayBuf = dsp::buffer::alloc<dsp::complex_t>(STREAM_BUFFER_SIZE + 64000);
|
|
||||||
dsp::buffer::clear(delayBuf, symbolSamps);
|
|
||||||
|
|
||||||
// Allocate and clear the history buffer
|
|
||||||
histBuf = dsp::buffer::alloc<dsp::complex_t>(prefixSamps);
|
|
||||||
dsp::buffer::clear(histBuf, prefixSamps);
|
|
||||||
|
|
||||||
// Compute the delay input addresses
|
|
||||||
delayBufInput = &delayBuf[symbolSamps];
|
|
||||||
|
|
||||||
// Compute the correlation AGC configuration
|
|
||||||
this->agcRate = agcRate;
|
|
||||||
agcRateInv = 1.0f - agcRate;
|
|
||||||
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
base_type::tempStop();
|
|
||||||
|
|
||||||
base_type::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
// Copy the data into the normal delay buffer
|
|
||||||
memcpy(delayBufInput, base_type::_in->readBuf, count * sizeof(dsp::complex_t));
|
|
||||||
|
|
||||||
// Flush the input stream
|
|
||||||
base_type::_in->flush();
|
|
||||||
|
|
||||||
// Do cross-correlation
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
// Get the current history slot
|
|
||||||
dsp::complex_t* slot = &histBuf[histId++];
|
|
||||||
|
|
||||||
// Wrap around the history slot index (TODO: Check that the history buffer's length is correct)
|
|
||||||
histId %= prefixSamps;
|
|
||||||
|
|
||||||
// Kick out last value from the correlation
|
|
||||||
corr -= *slot;
|
|
||||||
|
|
||||||
// Save input value and compute the new prodct
|
|
||||||
dsp::complex_t val = delayBuf[i];
|
|
||||||
dsp::complex_t prod = val.conj()*delayBuf[i+symbolSamps];
|
|
||||||
|
|
||||||
// Add the new value to the correlation
|
|
||||||
*slot = prod;
|
|
||||||
|
|
||||||
// Add the new value to the history buffer
|
|
||||||
corr += prod;
|
|
||||||
|
|
||||||
// Compute sample amplitude
|
|
||||||
float rcorr = corr.amplitude();
|
|
||||||
|
|
||||||
// If a high enough peak is reached, reset the symbol counter
|
|
||||||
if (rcorr > avgCorr && rcorr > peakCorr) { // Note keeping an average level might not be needed
|
|
||||||
peakCorr = rcorr;
|
|
||||||
peakLCorr = lastCorr;
|
|
||||||
samplesSincePeak = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is the sample right after the peak, save it
|
|
||||||
if (samplesSincePeak == 1) {
|
|
||||||
peakRCorr = rcorr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the sample to the output
|
|
||||||
out.writeBuf[samplesSincePeak++] = val;
|
|
||||||
|
|
||||||
// If the end of the symbol is reached, send it off
|
|
||||||
if (samplesSincePeak >= symbolSamps) {
|
|
||||||
if (!out.swap(symbolSamps)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
samplesSincePeak = 0;
|
|
||||||
peakCorr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the average correlation
|
|
||||||
lastCorr = rcorr;
|
|
||||||
|
|
||||||
// Update the average correlation value
|
|
||||||
avgCorr = agcRate*rcorr + agcRateInv*avgCorr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move unused data
|
|
||||||
memmove(delayBuf, &delayBuf[count], symbolSamps * sizeof(dsp::complex_t));
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int symbolSamps;
|
|
||||||
int prefixSamps;
|
|
||||||
|
|
||||||
int histId = 0;
|
|
||||||
dsp::complex_t* histBuf;
|
|
||||||
|
|
||||||
dsp::complex_t* delayBuf;
|
|
||||||
dsp::complex_t* delayBufInput;
|
|
||||||
|
|
||||||
dsp::complex_t corr = { 0.0f, 0.0f };
|
|
||||||
|
|
||||||
int samplesSincePeak = 0;
|
|
||||||
float lastCorr = 0.0f;
|
|
||||||
float peakCorr = 0.0f;
|
|
||||||
float peakLCorr = 0.0f;
|
|
||||||
float peakRCorr = 0.0f;
|
|
||||||
|
|
||||||
// Note only required for DAB
|
|
||||||
float avgCorr = 0.0f;
|
|
||||||
float agcRate;
|
|
||||||
float agcRateInv;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FrameFreqSync : public dsp::Processor<dsp::complex_t, dsp::complex_t> {
|
|
||||||
using base_type = dsp::Processor<dsp::complex_t, dsp::complex_t>;
|
|
||||||
public:
|
|
||||||
FrameFreqSync() {}
|
|
||||||
|
|
||||||
FrameFreqSync(dsp::stream<dsp::complex_t>* in, float agcRate = 0.01f) { init(in, agcRate); }
|
|
||||||
|
|
||||||
void init(dsp::stream<dsp::complex_t>* in, float agcRate = 0.01f) {
|
|
||||||
// Allocate buffers
|
|
||||||
amps = dsp::buffer::alloc<float>(2048);
|
|
||||||
conjRef = dsp::buffer::alloc<dsp::complex_t>(2048);
|
|
||||||
corrIn = (dsp::complex_t*)fftwf_alloc_complex(2048);
|
|
||||||
corrOut = (dsp::complex_t*)fftwf_alloc_complex(2048);
|
|
||||||
|
|
||||||
// Copy the phase reference
|
|
||||||
memcpy(conjRef, DAB_PHASE_SYM_CONJ, 2048 * sizeof(dsp::complex_t));
|
|
||||||
|
|
||||||
// Plan the FFT computation
|
|
||||||
plan = fftwf_plan_dft_1d(2048, (fftwf_complex*)corrIn, (fftwf_complex*)corrOut, FFTW_FORWARD, FFTW_ESTIMATE);
|
|
||||||
|
|
||||||
// Compute the correlation AGC configuration
|
|
||||||
this->agcRate = agcRate;
|
|
||||||
agcRateInv = 1.0f - agcRate;
|
|
||||||
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
assert(base_type::_block_init);
|
|
||||||
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
|
|
||||||
base_type::tempStop();
|
|
||||||
|
|
||||||
base_type::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
// Apply frequency shift
|
|
||||||
lv_32fc_t phase = lv_cmake(1.0f, 0.0f);
|
|
||||||
lv_32fc_t phaseDelta = lv_cmake(cos(offset), sin(offset));
|
|
||||||
#if VOLK_VERSION >= 030100
|
|
||||||
volk_32fc_s32fc_x2_rotator2_32fc((lv_32fc_t*)_in->readBuf, (lv_32fc_t*)_in->readBuf, phaseDelta, &phase, count);
|
|
||||||
#else
|
|
||||||
volk_32fc_s32fc_x2_rotator_32fc((lv_32fc_t*)_in->readBuf, (lv_32fc_t*)_in->readBuf, phaseDelta, &phase, count);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Compute the amplitude amplitude of all samples
|
|
||||||
volk_32fc_magnitude_32f(amps, (lv_32fc_t*)_in->readBuf, 2048);
|
|
||||||
|
|
||||||
// Compute the average signal level by adding up all values
|
|
||||||
float level = 0.0f;
|
|
||||||
volk_32f_accumulator_s32f(&level, amps, 2048);
|
|
||||||
|
|
||||||
// Detect a frame sync condition
|
|
||||||
if (level < avgLvl * 0.5f) {
|
|
||||||
// Reset symbol counter
|
|
||||||
sym = 1;
|
|
||||||
|
|
||||||
// Update the average level
|
|
||||||
avgLvl = agcRate*level + agcRateInv*avgLvl;
|
|
||||||
|
|
||||||
// Flush the input stream and return
|
|
||||||
base_type::_in->flush();
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the average level
|
|
||||||
avgLvl = agcRate*level + agcRateInv*avgLvl;
|
|
||||||
|
|
||||||
// Handle phase reference
|
|
||||||
if (sym == 1) {
|
|
||||||
// Output the symbols (DEBUG ONLY)
|
|
||||||
memcpy(corrIn, _in->readBuf, 2048 * sizeof(dsp::complex_t));
|
|
||||||
fftwf_execute(plan);
|
|
||||||
volk_32fc_magnitude_32f(amps, (lv_32fc_t*)corrOut, 2048);
|
|
||||||
int outCount = 0;
|
|
||||||
dsp::complex_t pi4 = { cos(3.1415926535*0.25), sin(3.1415926535*0.25) };
|
|
||||||
for (int i = -767; i < 768; i++) {
|
|
||||||
if (!i) { continue; }
|
|
||||||
int cid0 = ((i-1) >= 0) ? (i-1) : 2048+(i-1);
|
|
||||||
int cid1 = (i >= 0) ? i : 2048+i;;
|
|
||||||
out.writeBuf[outCount++] = pi4 * (corrOut[cid1] * corrOut[cid0].conj()) * (1.0f/(amps[cid0]*amps[cid0]));
|
|
||||||
}
|
|
||||||
out.swap(outCount);
|
|
||||||
|
|
||||||
// Multiply the samples with the conjugated phase reference signal
|
|
||||||
volk_32fc_x2_multiply_32fc((lv_32fc_t*)corrIn, (lv_32fc_t*)_in->readBuf, (lv_32fc_t*)conjRef, 2048);
|
|
||||||
|
|
||||||
// Compute the FFT of the product
|
|
||||||
fftwf_execute(plan);
|
|
||||||
|
|
||||||
// Compute the amplitude of the bins
|
|
||||||
volk_32fc_magnitude_32f(amps, (lv_32fc_t*)corrOut, 2048);
|
|
||||||
|
|
||||||
// Locate highest power bin
|
|
||||||
uint32_t peakId;
|
|
||||||
volk_32f_index_max_32u(&peakId, amps, 2048);
|
|
||||||
|
|
||||||
// Obtain the value of the bins next to the peak
|
|
||||||
float peakL = amps[(peakId + 2047) % 2048];
|
|
||||||
float peakR = amps[(peakId + 1) % 2048];
|
|
||||||
|
|
||||||
// Compute the integer frequency offset
|
|
||||||
float offInt = (peakId < 1024) ? (float)peakId : ((float)peakId - 2048.0f);
|
|
||||||
|
|
||||||
// Compute the frequency offset in rad/samp
|
|
||||||
float off = 3.1415926535f * (offInt + ((peakR - peakL) / (peakR + peakL))) * (1.0f / 1024.0f);
|
|
||||||
|
|
||||||
// Run control loop
|
|
||||||
offset -= 0.1f*off;
|
|
||||||
flog::debug("Offset: {} Hz, Error: {} Hz, Avg Level: {}", offset * (0.5f/3.1415926535f)*2.048e6, off * (0.5f/3.1415926535f)*2.048e6, avgLvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the symbol counter
|
|
||||||
sym++;
|
|
||||||
|
|
||||||
// Flush the input stream and return
|
|
||||||
base_type::_in->flush();
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
fftwf_plan plan;
|
|
||||||
|
|
||||||
float* amps;
|
|
||||||
dsp::complex_t* conjRef;
|
|
||||||
dsp::complex_t* corrIn;
|
|
||||||
dsp::complex_t* corrOut;
|
|
||||||
|
|
||||||
int sym;
|
|
||||||
float offset = 0.0f;
|
|
||||||
|
|
||||||
float avgLvl = 0.0f;
|
|
||||||
float agcRate;
|
|
||||||
float agcRateInv;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
|||||||
#include <imgui.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <core.h>
|
|
||||||
#include <gui/style.h>
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <signal_path/signal_path.h>
|
|
||||||
#include <module.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <dsp/stream.h>
|
|
||||||
#include <dsp/buffer/reshaper.h>
|
|
||||||
#include <dsp/multirate/rational_resampler.h>
|
|
||||||
#include <dsp/sink/handler_sink.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <chrono>
|
|
||||||
#include "dab_dsp.h"
|
|
||||||
#include <gui/widgets/constellation_diagram.h>
|
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
|
||||||
|
|
||||||
SDRPP_MOD_INFO{
|
|
||||||
/* Name: */ "dab_decoder",
|
|
||||||
/* Description: */ "DAB/DAB+ Decoder for SDR++",
|
|
||||||
/* Author: */ "Ryzerth",
|
|
||||||
/* Version: */ 0, 1, 0,
|
|
||||||
/* Max instances */ -1
|
|
||||||
};
|
|
||||||
|
|
||||||
ConfigManager config;
|
|
||||||
|
|
||||||
#define INPUT_SAMPLE_RATE 2.048e6
|
|
||||||
#define VFO_BANDWIDTH 1.6e6
|
|
||||||
|
|
||||||
class M17DecoderModule : public ModuleManager::Instance {
|
|
||||||
public:
|
|
||||||
M17DecoderModule(std::string name) {
|
|
||||||
this->name = name;
|
|
||||||
|
|
||||||
file = std::ofstream("sync4.f32", std::ios::out | std::ios::binary);
|
|
||||||
|
|
||||||
// Load config
|
|
||||||
config.acquire();
|
|
||||||
|
|
||||||
config.release(true);
|
|
||||||
|
|
||||||
// Initialize VFO
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, VFO_BANDWIDTH, INPUT_SAMPLE_RATE, VFO_BANDWIDTH, VFO_BANDWIDTH, true);
|
|
||||||
vfo->setSnapInterval(250);
|
|
||||||
|
|
||||||
// Initialize DSP here
|
|
||||||
csync.init(vfo->output, 1e-3, 246e-6, INPUT_SAMPLE_RATE);
|
|
||||||
ffsync.init(&csync.out);
|
|
||||||
ns.init(&ffsync.out, handler, this);
|
|
||||||
|
|
||||||
// Start DSO Here
|
|
||||||
csync.start();
|
|
||||||
ffsync.start();
|
|
||||||
ns.start();
|
|
||||||
|
|
||||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~M17DecoderModule() {
|
|
||||||
gui::menu.removeEntry(name);
|
|
||||||
// Stop DSP Here
|
|
||||||
if (enabled) {
|
|
||||||
csync.stop();
|
|
||||||
ffsync.stop();
|
|
||||||
ns.stop();
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
sigpath::sinkManager.unregisterStream(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void postInit() {}
|
|
||||||
|
|
||||||
void enable() {
|
|
||||||
double bw = gui::waterfall.getBandwidth();
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), VFO_BANDWIDTH, INPUT_SAMPLE_RATE, VFO_BANDWIDTH, VFO_BANDWIDTH, true);
|
|
||||||
vfo->setSnapInterval(250);
|
|
||||||
|
|
||||||
// Set Input of demod here
|
|
||||||
csync.setInput(vfo->output);
|
|
||||||
|
|
||||||
// Start DSP here
|
|
||||||
csync.start();
|
|
||||||
ffsync.start();
|
|
||||||
ns.start();
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable() {
|
|
||||||
// Stop DSP here
|
|
||||||
csync.stop();
|
|
||||||
ffsync.stop();
|
|
||||||
ns.stop();
|
|
||||||
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void menuHandler(void* ctx) {
|
|
||||||
M17DecoderModule* _this = (M17DecoderModule*)ctx;
|
|
||||||
|
|
||||||
float menuWidth = ImGui::GetContentRegionAvail().x;
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::beginDisabled(); }
|
|
||||||
|
|
||||||
_this->constDiagram.draw();
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::endDisabled(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream file;
|
|
||||||
|
|
||||||
static void handler(dsp::complex_t* data, int count, void* ctx) {
|
|
||||||
M17DecoderModule* _this = (M17DecoderModule*)ctx;
|
|
||||||
//_this->file.write((char*)data, count * sizeof(dsp::complex_t));
|
|
||||||
|
|
||||||
dsp::complex_t* buf = _this->constDiagram.acquireBuffer();
|
|
||||||
memcpy(buf, data, 1024 * sizeof(dsp::complex_t));
|
|
||||||
_this->constDiagram.releaseBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool enabled = true;
|
|
||||||
|
|
||||||
dab::CyclicSync csync;
|
|
||||||
dab::FrameFreqSync ffsync;
|
|
||||||
dsp::sink::Handler<dsp::complex_t> ns;
|
|
||||||
|
|
||||||
ImGui::ConstellationDiagram constDiagram;
|
|
||||||
|
|
||||||
// DSP Chain
|
|
||||||
VFOManager::VFO* vfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
MOD_EXPORT void _INIT_() {
|
|
||||||
// Create default recording directory
|
|
||||||
json def = json({});
|
|
||||||
config.setPath(core::args["root"].s() + "/dab_decoder_config.json");
|
|
||||||
config.load(def);
|
|
||||||
config.enableAutoSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
|
|
||||||
return new M17DecoderModule(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
|
|
||||||
delete (M17DecoderModule*)instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _END_() {
|
|
||||||
config.disableAutoSave();
|
|
||||||
config.save();
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
0123456789
|
|
||||||
--- ---
|
|
||||||
|
|
||||||
0*4
|
|
||||||
1*5
|
|
||||||
2*6
|
|
||||||
|
|
||||||
1*5
|
|
||||||
2*6 = L + 3*7 - 0*4
|
|
||||||
3*7
|
|
||||||
|
|
||||||
2*6
|
|
||||||
3*7 = L + 4*8 - 1*5
|
|
||||||
4*8
|
|
||||||
|
|
||||||
3*7
|
|
||||||
4*8 = L + 5*9 - 2*6
|
|
||||||
5*9
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
0*5
|
|
||||||
1*6
|
|
||||||
2*7
|
|
||||||
|
|
||||||
1*6
|
|
||||||
2*7
|
|
||||||
3*8
|
|
||||||
|
|
||||||
2*7
|
|
||||||
3*8
|
|
||||||
4*9
|
|
||||||
|
|
||||||
=> Use same technique to cache the interpolation results
|
|
||||||
@@ -8,15 +8,15 @@
|
|||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
#include "pocsag.h"
|
#include "pocsag.h"
|
||||||
|
|
||||||
#define BAUDRATE 2400
|
|
||||||
#define SAMPLERATE (BAUDRATE*10)
|
|
||||||
|
|
||||||
class POCSAGDecoder : public Decoder {
|
class POCSAGDecoder : public Decoder {
|
||||||
public:
|
public:
|
||||||
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, BAUDRATE) {
|
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 2400) {
|
||||||
this->name = name;
|
this->name = name;
|
||||||
this->vfo = vfo;
|
this->vfo = vfo;
|
||||||
|
|
||||||
|
// Default baudrate (TODO: Load from config)
|
||||||
|
baudrate = 2400;
|
||||||
|
|
||||||
// Define baudrate options
|
// Define baudrate options
|
||||||
baudrates.define(512, "512 Baud", 512);
|
baudrates.define(512, "512 Baud", 512);
|
||||||
baudrates.define(1200, "1200 Baud", 1200);
|
baudrates.define(1200, "1200 Baud", 1200);
|
||||||
@@ -24,9 +24,9 @@ public:
|
|||||||
|
|
||||||
// Init DSP
|
// Init DSP
|
||||||
vfo->setBandwidthLimits(12500, 12500, true);
|
vfo->setBandwidthLimits(12500, 12500, true);
|
||||||
vfo->setSampleRate(SAMPLERATE, 12500);
|
vfo->setSampleRate(baudrate*10.0, 12500);
|
||||||
dsp.init(vfo->output, SAMPLERATE, BAUDRATE);
|
dsp.init(vfo->output, baudrate*10.0, baudrate);
|
||||||
reshape.init(&dsp.soft, BAUDRATE, (BAUDRATE / 30.0) - BAUDRATE);
|
reshape.init(&dsp.soft, baudrate, (baudrate / 30.0) - baudrate);
|
||||||
dataHandler.init(&dsp.out, _dataHandler, this);
|
dataHandler.init(&dsp.out, _dataHandler, this);
|
||||||
diagHandler.init(&reshape.out, _diagHandler, this);
|
diagHandler.init(&reshape.out, _diagHandler, this);
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
ImGui::LeftLabel("Baudrate");
|
ImGui::LeftLabel("Baudrate");
|
||||||
ImGui::FillWidth();
|
ImGui::FillWidth();
|
||||||
if (ImGui::Combo(("##pager_decoder_pocsag_br_" + name).c_str(), &brId, baudrates.txt)) {
|
if (ImGui::Combo(("##pager_decoder_pocsag_br_" + name).c_str(), &brId, baudrates.txt)) {
|
||||||
// TODO
|
setBaudrate(baudrates.value(brId));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::FillWidth();
|
ImGui::FillWidth();
|
||||||
@@ -79,7 +79,8 @@ private:
|
|||||||
static void _diagHandler(float* data, int count, void* ctx) {
|
static void _diagHandler(float* data, int count, void* ctx) {
|
||||||
POCSAGDecoder* _this = (POCSAGDecoder*)ctx;
|
POCSAGDecoder* _this = (POCSAGDecoder*)ctx;
|
||||||
float* buf = _this->diag.acquireBuffer();
|
float* buf = _this->diag.acquireBuffer();
|
||||||
memcpy(buf, data, count * sizeof(float));
|
int maxCount = std::min<int>(count, _this->diag.getCount());
|
||||||
|
memcpy(buf, data, maxCount * sizeof(float));
|
||||||
_this->diag.releaseBuffer();
|
_this->diag.releaseBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +88,15 @@ private:
|
|||||||
flog::debug("[{}]: '{}'", (uint32_t)addr, msg);
|
flog::debug("[{}]: '{}'", (uint32_t)addr, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setBaudrate(double baudrate) {
|
||||||
|
vfo->setSampleRate(baudrate*10.0, 12500);
|
||||||
|
stop();
|
||||||
|
reshape.setKeep(baudrate);
|
||||||
|
reshape.setSkip((baudrate / 30.0) - baudrate);
|
||||||
|
diag.setCount(baudrate);
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
VFOManager::VFO* vfo;
|
VFOManager::VFO* vfo;
|
||||||
|
|
||||||
@@ -100,6 +110,7 @@ private:
|
|||||||
ImGui::SymbolDiagram diag;
|
ImGui::SymbolDiagram diag;
|
||||||
|
|
||||||
int brId = 2;
|
int brId = 2;
|
||||||
|
double baudrate = 2400;
|
||||||
|
|
||||||
OptionList<int, int> baudrates;
|
OptionList<int, int> baudrates;
|
||||||
};
|
};
|
||||||
@@ -20,16 +20,6 @@ enum IFNRPreset {
|
|||||||
IFNR_PRESET_BROADCAST
|
IFNR_PRESET_BROADCAST
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SquelchMode {
|
|
||||||
SQUELCH_MODE_OFF,
|
|
||||||
SQUELCH_MODE_POWER,
|
|
||||||
SQUELCH_MODE_SNR,
|
|
||||||
SQUELCH_MODE_CTCSS_MUTE,
|
|
||||||
SQUELCH_MODE_CTCSS_DECODE,
|
|
||||||
SQUELCH_MODE_DCS_MUTE,
|
|
||||||
SQUELCH_MODE_DCS_DECODE,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace demod {
|
namespace demod {
|
||||||
class Demodulator {
|
class Demodulator {
|
||||||
public:
|
public:
|
||||||
@@ -55,8 +45,6 @@ namespace demod {
|
|||||||
virtual int getDefaultDeemphasisMode() = 0;
|
virtual int getDefaultDeemphasisMode() = 0;
|
||||||
virtual bool getFMIFNRAllowed() = 0;
|
virtual bool getFMIFNRAllowed() = 0;
|
||||||
virtual bool getNBAllowed() = 0;
|
virtual bool getNBAllowed() = 0;
|
||||||
virtual bool getHighPassAllowed() = 0;
|
|
||||||
virtual bool getSquelchAllowed() = 0;
|
|
||||||
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
|
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,6 @@ namespace demod {
|
|||||||
|
|
||||||
void showMenu() {
|
void showMenu() {
|
||||||
float menuWidth = ImGui::GetContentRegionAvail().x;
|
float menuWidth = ImGui::GetContentRegionAvail().x;
|
||||||
if (ImGui::Checkbox(("Carrier AGC##_radio_am_carrier_agc_" + name).c_str(), &carrierAgc)) {
|
|
||||||
demod.setAGCMode(carrierAgc ? dsp::demod::AM<dsp::stereo_t>::AGCMode::CARRIER : dsp::demod::AM<dsp::stereo_t>::AGCMode::AUDIO);
|
|
||||||
_config->acquire();
|
|
||||||
_config->conf[name][getName()]["carrierAgc"] = carrierAgc;
|
|
||||||
_config->release(true);
|
|
||||||
}
|
|
||||||
ImGui::LeftLabel("AGC Attack");
|
ImGui::LeftLabel("AGC Attack");
|
||||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||||
if (ImGui::SliderFloat(("##_radio_am_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 200.0f)) {
|
if (ImGui::SliderFloat(("##_radio_am_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 200.0f)) {
|
||||||
@@ -62,6 +56,12 @@ namespace demod {
|
|||||||
_config->conf[name][getName()]["agcDecay"] = agcDecay;
|
_config->conf[name][getName()]["agcDecay"] = agcDecay;
|
||||||
_config->release(true);
|
_config->release(true);
|
||||||
}
|
}
|
||||||
|
if (ImGui::Checkbox(("Carrier AGC##_radio_am_carrier_agc_" + name).c_str(), &carrierAgc)) {
|
||||||
|
demod.setAGCMode(carrierAgc ? dsp::demod::AM<dsp::stereo_t>::AGCMode::CARRIER : dsp::demod::AM<dsp::stereo_t>::AGCMode::AUDIO);
|
||||||
|
_config->acquire();
|
||||||
|
_config->conf[name][getName()]["carrierAgc"] = carrierAgc;
|
||||||
|
_config->release(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBandwidth(double bandwidth) { demod.setBandwidth(bandwidth); }
|
void setBandwidth(double bandwidth) { demod.setBandwidth(bandwidth); }
|
||||||
@@ -86,8 +86,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return false; }
|
bool getNBAllowed() { return false; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return false; }
|
bool getNBAllowed() { return false; }
|
||||||
bool getHighPassAllowed() { return false; }
|
|
||||||
bool getSquelchAllowed() { return false; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return true; }
|
bool getNBAllowed() { return true; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return true; }
|
bool getNBAllowed() { return true; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -22,11 +22,14 @@ namespace demod {
|
|||||||
if (config->conf[name][getName()].contains("lowPass")) {
|
if (config->conf[name][getName()].contains("lowPass")) {
|
||||||
_lowPass = config->conf[name][getName()]["lowPass"];
|
_lowPass = config->conf[name][getName()]["lowPass"];
|
||||||
}
|
}
|
||||||
|
if (config->conf[name][getName()].contains("highPass")) {
|
||||||
|
_highPass = config->conf[name][getName()]["highPass"];
|
||||||
|
}
|
||||||
_config->release();
|
_config->release();
|
||||||
|
|
||||||
|
|
||||||
// Define structure
|
// Define structure
|
||||||
demod.init(input, getIFSampleRate(), bandwidth, _lowPass);
|
demod.init(input, getIFSampleRate(), bandwidth, _lowPass, _highPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start() { demod.start(); }
|
void start() { demod.start(); }
|
||||||
@@ -40,6 +43,12 @@ namespace demod {
|
|||||||
_config->conf[name][getName()]["lowPass"] = _lowPass;
|
_config->conf[name][getName()]["lowPass"] = _lowPass;
|
||||||
_config->release(true);
|
_config->release(true);
|
||||||
}
|
}
|
||||||
|
if (ImGui::Checkbox(("High Pass##_radio_wfm_highpass_" + name).c_str(), &_highPass)) {
|
||||||
|
demod.setHighPass(_highPass);
|
||||||
|
_config->acquire();
|
||||||
|
_config->conf[name][getName()]["highPass"] = _highPass;
|
||||||
|
_config->release(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBandwidth(double bandwidth) {
|
void setBandwidth(double bandwidth) {
|
||||||
@@ -66,8 +75,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return true; }
|
bool getFMIFNRAllowed() { return true; }
|
||||||
bool getNBAllowed() { return false; }
|
bool getNBAllowed() { return false; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -76,6 +83,7 @@ namespace demod {
|
|||||||
ConfigManager* _config = NULL;
|
ConfigManager* _config = NULL;
|
||||||
|
|
||||||
bool _lowPass = true;
|
bool _lowPass = true;
|
||||||
|
bool _highPass = false;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,8 +59,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return true; }
|
bool getNBAllowed() { return true; }
|
||||||
bool getHighPassAllowed() { return false; }
|
|
||||||
bool getSquelchAllowed() { return false; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -80,8 +80,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||||
bool getFMIFNRAllowed() { return false; }
|
bool getFMIFNRAllowed() { return false; }
|
||||||
bool getNBAllowed() { return true; }
|
bool getNBAllowed() { return true; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -100,18 +100,18 @@ namespace demod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showMenu() {
|
void showMenu() {
|
||||||
if (ImGui::Checkbox(("Low Pass##_radio_wfm_lowpass_" + name).c_str(), &_lowPass)) {
|
|
||||||
demod.setLowPass(_lowPass);
|
|
||||||
_config->acquire();
|
|
||||||
_config->conf[name][getName()]["lowPass"] = _lowPass;
|
|
||||||
_config->release(true);
|
|
||||||
}
|
|
||||||
if (ImGui::Checkbox(("Stereo##_radio_wfm_stereo_" + name).c_str(), &_stereo)) {
|
if (ImGui::Checkbox(("Stereo##_radio_wfm_stereo_" + name).c_str(), &_stereo)) {
|
||||||
setStereo(_stereo);
|
setStereo(_stereo);
|
||||||
_config->acquire();
|
_config->acquire();
|
||||||
_config->conf[name][getName()]["stereo"] = _stereo;
|
_config->conf[name][getName()]["stereo"] = _stereo;
|
||||||
_config->release(true);
|
_config->release(true);
|
||||||
}
|
}
|
||||||
|
if (ImGui::Checkbox(("Low Pass##_radio_wfm_lowpass_" + name).c_str(), &_lowPass)) {
|
||||||
|
demod.setLowPass(_lowPass);
|
||||||
|
_config->acquire();
|
||||||
|
_config->conf[name][getName()]["lowPass"] = _lowPass;
|
||||||
|
_config->release(true);
|
||||||
|
}
|
||||||
if (ImGui::Checkbox(("Decode RDS##_radio_wfm_rds_" + name).c_str(), &_rds)) {
|
if (ImGui::Checkbox(("Decode RDS##_radio_wfm_rds_" + name).c_str(), &_rds)) {
|
||||||
demod.setRDSOut(_rds);
|
demod.setRDSOut(_rds);
|
||||||
_config->acquire();
|
_config->acquire();
|
||||||
@@ -270,8 +270,6 @@ namespace demod {
|
|||||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
|
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
|
||||||
bool getFMIFNRAllowed() { return true; }
|
bool getFMIFNRAllowed() { return true; }
|
||||||
bool getNBAllowed() { return false; }
|
bool getNBAllowed() { return false; }
|
||||||
bool getHighPassAllowed() { return true; }
|
|
||||||
bool getSquelchAllowed() { return true; }
|
|
||||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||||
|
|
||||||
// ============= DEDICATED FUNCTIONS =============
|
// ============= DEDICATED FUNCTIONS =============
|
||||||
|
|||||||
@@ -5,14 +5,10 @@ enum {
|
|||||||
RADIO_IFACE_CMD_SET_MODE,
|
RADIO_IFACE_CMD_SET_MODE,
|
||||||
RADIO_IFACE_CMD_GET_BANDWIDTH,
|
RADIO_IFACE_CMD_GET_BANDWIDTH,
|
||||||
RADIO_IFACE_CMD_SET_BANDWIDTH,
|
RADIO_IFACE_CMD_SET_BANDWIDTH,
|
||||||
RADIO_IFACE_CMD_GET_SQUELCH_MODE,
|
RADIO_IFACE_CMD_GET_SQUELCH_ENABLED,
|
||||||
RADIO_IFACE_CMD_SET_SQUELCH_MODE,
|
RADIO_IFACE_CMD_SET_SQUELCH_ENABLED,
|
||||||
RADIO_IFACE_CMD_GET_SQUELCH_LEVEL,
|
RADIO_IFACE_CMD_GET_SQUELCH_LEVEL,
|
||||||
RADIO_IFACE_CMD_SET_SQUELCH_LEVEL,
|
RADIO_IFACE_CMD_SET_SQUELCH_LEVEL,
|
||||||
RADIO_IFACE_CMD_GET_CTCSS_TONE,
|
|
||||||
RADIO_IFACE_CMD_SET_CTCSS_TONE,
|
|
||||||
RADIO_IFACE_CMD_GET_HIGHPASS,
|
|
||||||
RADIO_IFACE_CMD_SET_HIGHPASS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
#include <dsp/chain.h>
|
#include <dsp/chain.h>
|
||||||
#include <dsp/noise_reduction/noise_blanker.h>
|
#include <dsp/noise_reduction/noise_blanker.h>
|
||||||
#include <dsp/noise_reduction/fm_if.h>
|
#include <dsp/noise_reduction/fm_if.h>
|
||||||
#include <dsp/noise_reduction/power_squelch.h>
|
#include <dsp/noise_reduction/squelch.h>
|
||||||
#include <dsp/noise_reduction/ctcss_squelch.h>
|
|
||||||
#include <dsp/multirate/rational_resampler.h>
|
#include <dsp/multirate/rational_resampler.h>
|
||||||
#include <dsp/filter/deephasis.h>
|
#include <dsp/filter/deephasis.h>
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
@@ -50,22 +49,6 @@ public:
|
|||||||
ifnrPresets.define("Voice", IFNR_PRESET_VOICE);
|
ifnrPresets.define("Voice", IFNR_PRESET_VOICE);
|
||||||
ifnrPresets.define("Narrow Band", IFNR_PRESET_NARROW_BAND);
|
ifnrPresets.define("Narrow Band", IFNR_PRESET_NARROW_BAND);
|
||||||
|
|
||||||
squelchModes.define("off", "Off", SQUELCH_MODE_OFF);
|
|
||||||
squelchModes.define("power", "Power", SQUELCH_MODE_POWER);
|
|
||||||
//squelchModes.define("snr", "SNR", SQUELCH_MODE_SNR);
|
|
||||||
squelchModes.define("ctcss_mute", "CTCSS (Mute)", SQUELCH_MODE_CTCSS_MUTE);
|
|
||||||
squelchModes.define("ctcss_decode", "CTCSS (Decode Only)", SQUELCH_MODE_CTCSS_DECODE);
|
|
||||||
//squelchModes.define("dcs_mute", "DCS (Mute)", SQUELCH_MODE_DCS_MUTE);
|
|
||||||
//squelchModes.define("dcs_decode", "DCS (Decode Only)", SQUELCH_MODE_DCS_DECODE);
|
|
||||||
|
|
||||||
for (int i = 0; i < dsp::noise_reduction::_CTCSS_TONE_COUNT; i++) {
|
|
||||||
float tone = dsp::noise_reduction::CTCSS_TONES[i];
|
|
||||||
char buf[64];
|
|
||||||
sprintf(buf, "%.1fHz", tone);
|
|
||||||
ctcssTones.define((int)round(tone) * 10, buf, (dsp::noise_reduction::CTCSSTone)i);
|
|
||||||
}
|
|
||||||
ctcssTones.define(-1, "Any", dsp::noise_reduction::CTCSS_TONE_ANY);
|
|
||||||
|
|
||||||
// Initialize the config if it doesn't exist
|
// Initialize the config if it doesn't exist
|
||||||
bool created = false;
|
bool created = false;
|
||||||
config.acquire();
|
config.acquire();
|
||||||
@@ -89,24 +72,19 @@ public:
|
|||||||
|
|
||||||
nb.init(NULL, 500.0 / 24000.0, 10.0);
|
nb.init(NULL, 500.0 / 24000.0, 10.0);
|
||||||
fmnr.init(NULL, 32);
|
fmnr.init(NULL, 32);
|
||||||
powerSquelch.init(NULL, MIN_SQUELCH);
|
squelch.init(NULL, MIN_SQUELCH);
|
||||||
|
|
||||||
ifChain.addBlock(&nb, false);
|
ifChain.addBlock(&nb, false);
|
||||||
ifChain.addBlock(&powerSquelch, false);
|
ifChain.addBlock(&squelch, false);
|
||||||
ifChain.addBlock(&fmnr, false);
|
ifChain.addBlock(&fmnr, false);
|
||||||
|
|
||||||
// Initialize audio DSP chain
|
// Initialize audio DSP chain
|
||||||
afChain.init(&dummyAudioStream);
|
afChain.init(&dummyAudioStream);
|
||||||
|
|
||||||
ctcss.init(NULL, 50000.0);
|
|
||||||
resamp.init(NULL, 250000.0, 48000.0);
|
resamp.init(NULL, 250000.0, 48000.0);
|
||||||
hpTaps = dsp::taps::highPass(300.0, 100.0, 48000.0);
|
|
||||||
hpf.init(NULL, hpTaps);
|
|
||||||
deemp.init(NULL, 50e-6, 48000.0);
|
deemp.init(NULL, 50e-6, 48000.0);
|
||||||
|
|
||||||
afChain.addBlock(&ctcss, false);
|
|
||||||
afChain.addBlock(&resamp, true);
|
afChain.addBlock(&resamp, true);
|
||||||
afChain.addBlock(&hpf, false);
|
|
||||||
afChain.addBlock(&deemp, false);
|
afChain.addBlock(&deemp, false);
|
||||||
|
|
||||||
// Initialize the sink
|
// Initialize the sink
|
||||||
@@ -255,33 +233,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Squelch
|
|
||||||
if (_this->squelchAllowed) {
|
|
||||||
ImGui::LeftLabel("Squelch Mode");
|
|
||||||
ImGui::FillWidth();
|
|
||||||
if (ImGui::Combo(("##_radio_sqelch_mode_" + _this->name).c_str(), &_this->squelchModeId, _this->squelchModes.txt)) {
|
|
||||||
_this->setSquelchMode(_this->squelchModes[_this->squelchModeId]);
|
|
||||||
}
|
|
||||||
switch (_this->squelchModes[_this->squelchModeId]) {
|
|
||||||
case SQUELCH_MODE_POWER:
|
|
||||||
ImGui::LeftLabel("Squelch Level");
|
|
||||||
ImGui::FillWidth();
|
|
||||||
if (ImGui::SliderFloat(("##_radio_sqelch_lvl_" + _this->name).c_str(), &_this->squelchLevel, _this->MIN_SQUELCH, _this->MAX_SQUELCH, "%.3fdB")) {
|
|
||||||
_this->setSquelchLevel(_this->squelchLevel);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_CTCSS_MUTE:
|
|
||||||
if (_this->squelchModes[_this->squelchModeId] == SQUELCH_MODE_CTCSS_MUTE) {
|
|
||||||
ImGui::LeftLabel("CTCSS Tone");
|
|
||||||
ImGui::FillWidth();
|
|
||||||
if (ImGui::Combo(("##_radio_ctcss_tone_" + _this->name).c_str(), &_this->ctcssToneId, _this->ctcssTones.txt)) {
|
|
||||||
_this->setCTCSSTone(_this->ctcssTones[_this->ctcssToneId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Noise blanker
|
// Noise blanker
|
||||||
if (_this->nbAllowed) {
|
if (_this->nbAllowed) {
|
||||||
if (ImGui::Checkbox(("Noise blanker (W.I.P.)##_radio_nb_ena_" + _this->name).c_str(), &_this->nbEnabled)) {
|
if (ImGui::Checkbox(("Noise blanker (W.I.P.)##_radio_nb_ena_" + _this->name).c_str(), &_this->nbEnabled)) {
|
||||||
@@ -296,6 +247,19 @@ private:
|
|||||||
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
|
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Squelch
|
||||||
|
if (ImGui::Checkbox(("Squelch##_radio_sqelch_ena_" + _this->name).c_str(), &_this->squelchEnabled)) {
|
||||||
|
_this->setSquelchEnabled(_this->squelchEnabled);
|
||||||
|
}
|
||||||
|
if (!_this->squelchEnabled && _this->enabled) { style::beginDisabled(); }
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||||
|
if (ImGui::SliderFloat(("##_radio_sqelch_lvl_" + _this->name).c_str(), &_this->squelchLevel, _this->MIN_SQUELCH, _this->MAX_SQUELCH, "%.3fdB")) {
|
||||||
|
_this->setSquelchLevel(_this->squelchLevel);
|
||||||
|
}
|
||||||
|
if (!_this->squelchEnabled && _this->enabled) { style::endDisabled(); }
|
||||||
|
|
||||||
// FM IF Noise Reduction
|
// FM IF Noise Reduction
|
||||||
if (_this->FMIFNRAllowed) {
|
if (_this->FMIFNRAllowed) {
|
||||||
if (ImGui::Checkbox(("IF Noise Reduction##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->FMIFNREnabled)) {
|
if (ImGui::Checkbox(("IF Noise Reduction##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->FMIFNREnabled)) {
|
||||||
@@ -312,53 +276,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// High pass
|
|
||||||
if (_this->highPassAllowed) {
|
|
||||||
if (ImGui::Checkbox(("High Pass##_radio_hpf_" + _this->name).c_str(), &_this->highPass)) {
|
|
||||||
_this->setHighPass(_this->highPass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Demodulator specific menu
|
// Demodulator specific menu
|
||||||
_this->selectedDemod->showMenu();
|
_this->selectedDemod->showMenu();
|
||||||
|
|
||||||
// Display the squelch diagnostics
|
|
||||||
switch (_this->squelchModes[_this->squelchModeId]) {
|
|
||||||
case SQUELCH_MODE_CTCSS_MUTE:
|
|
||||||
ImGui::TextUnformatted("Received Tone:");
|
|
||||||
ImGui::SameLine();
|
|
||||||
{
|
|
||||||
auto ctone = _this->ctcss.getCurrentTone();
|
|
||||||
auto dtone = _this->ctcssTones[_this->ctcssToneId];
|
|
||||||
if (ctone != dsp::noise_reduction::CTCSS_TONE_NONE) {
|
|
||||||
if (dtone == dsp::noise_reduction::CTCSS_TONE_ANY || ctone == dtone) {
|
|
||||||
ImGui::TextColored(ImVec4(0, 1, 0, 1), "%.1fHz", dsp::noise_reduction::CTCSS_TONES[_this->ctcss.getCurrentTone()]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "%.1fHz", dsp::noise_reduction::CTCSS_TONES[_this->ctcss.getCurrentTone()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ImGui::TextUnformatted("None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_CTCSS_DECODE:
|
|
||||||
ImGui::TextUnformatted("Received Tone:");
|
|
||||||
ImGui::SameLine();
|
|
||||||
{
|
|
||||||
auto ctone = _this->ctcss.getCurrentTone();
|
|
||||||
if (ctone != dsp::noise_reduction::CTCSS_TONE_NONE) {
|
|
||||||
ImGui::TextColored(ImVec4(0, 1, 0, 1), "%.1fHz", dsp::noise_reduction::CTCSS_TONES[_this->ctcss.getCurrentTone()]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ImGui::TextUnformatted("None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::endDisabled(); }
|
if (!_this->enabled) { style::endDisabled(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,20 +360,15 @@ private:
|
|||||||
maxBandwidth = selectedDemod->getMaxBandwidth();
|
maxBandwidth = selectedDemod->getMaxBandwidth();
|
||||||
bandwidthLocked = selectedDemod->getBandwidthLocked();
|
bandwidthLocked = selectedDemod->getBandwidthLocked();
|
||||||
snapInterval = selectedDemod->getDefaultSnapInterval();
|
snapInterval = selectedDemod->getDefaultSnapInterval();
|
||||||
|
squelchLevel = MIN_SQUELCH;
|
||||||
deempAllowed = selectedDemod->getDeempAllowed();
|
deempAllowed = selectedDemod->getDeempAllowed();
|
||||||
deempId = deempModes.valueId((DeemphasisMode)selectedDemod->getDefaultDeemphasisMode());
|
deempId = deempModes.valueId((DeemphasisMode)selectedDemod->getDefaultDeemphasisMode());
|
||||||
squelchModeId = squelchModes.valueId(SQUELCH_MODE_OFF);
|
squelchEnabled = false;
|
||||||
squelchLevel = MIN_SQUELCH;
|
|
||||||
ctcssToneId = ctcssTones.valueId(dsp::noise_reduction::CTCSS_TONE_67Hz);
|
|
||||||
highPass = false;
|
|
||||||
|
|
||||||
postProcEnabled = selectedDemod->getPostProcEnabled();
|
postProcEnabled = selectedDemod->getPostProcEnabled();
|
||||||
FMIFNRAllowed = selectedDemod->getFMIFNRAllowed();
|
FMIFNRAllowed = selectedDemod->getFMIFNRAllowed();
|
||||||
FMIFNREnabled = false;
|
FMIFNREnabled = false;
|
||||||
fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE);
|
fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE);
|
||||||
nbAllowed = selectedDemod->getNBAllowed();
|
nbAllowed = selectedDemod->getNBAllowed();
|
||||||
squelchAllowed = selectedDemod->getSquelchAllowed();
|
|
||||||
highPassAllowed = selectedDemod->getHighPassAllowed();
|
|
||||||
nbEnabled = false;
|
nbEnabled = false;
|
||||||
nbLevel = 0.0f;
|
nbLevel = 0.0f;
|
||||||
double ifSamplerate = selectedDemod->getIFSampleRate();
|
double ifSamplerate = selectedDemod->getIFSampleRate();
|
||||||
@@ -465,24 +380,11 @@ private:
|
|||||||
if (config.conf[name][selectedDemod->getName()].contains("snapInterval")) {
|
if (config.conf[name][selectedDemod->getName()].contains("snapInterval")) {
|
||||||
snapInterval = config.conf[name][selectedDemod->getName()]["snapInterval"];
|
snapInterval = config.conf[name][selectedDemod->getName()]["snapInterval"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("squelchMode")) {
|
|
||||||
std::string squelchModeStr = config.conf[name][selectedDemod->getName()]["squelchMode"];
|
|
||||||
if (squelchModes.keyExists(squelchModeStr)) {
|
|
||||||
squelchModeId = squelchModes.keyId(squelchModeStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("squelchLevel")) {
|
if (config.conf[name][selectedDemod->getName()].contains("squelchLevel")) {
|
||||||
squelchLevel = config.conf[name][selectedDemod->getName()]["squelchLevel"];
|
squelchLevel = config.conf[name][selectedDemod->getName()]["squelchLevel"];
|
||||||
}
|
}
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("ctcssTone")) {
|
if (config.conf[name][selectedDemod->getName()].contains("squelchEnabled")) {
|
||||||
int ctcssToneX10 = config.conf[name][selectedDemod->getName()]["ctcssTone"];
|
squelchEnabled = config.conf[name][selectedDemod->getName()]["squelchEnabled"];
|
||||||
if (ctcssTones.keyExists(ctcssToneX10)) {
|
|
||||||
ctcssToneId = ctcssTones.keyId(ctcssToneX10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("highPass")) {
|
|
||||||
highPass = config.conf[name][selectedDemod->getName()]["highPass"];
|
|
||||||
}
|
}
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("deempMode")) {
|
if (config.conf[name][selectedDemod->getName()].contains("deempMode")) {
|
||||||
if (!config.conf[name][selectedDemod->getName()]["deempMode"].is_string()) {
|
if (!config.conf[name][selectedDemod->getName()]["deempMode"].is_string()) {
|
||||||
@@ -532,22 +434,16 @@ private:
|
|||||||
setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false);
|
setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false);
|
||||||
|
|
||||||
// Configure squelch
|
// Configure squelch
|
||||||
setSquelchMode(squelchAllowed ? squelchModes[squelchModeId] : SQUELCH_MODE_OFF);
|
|
||||||
setSquelchLevel(squelchLevel);
|
setSquelchLevel(squelchLevel);
|
||||||
setCTCSSTone(ctcssTones[ctcssToneId]);
|
setSquelchEnabled(squelchEnabled);
|
||||||
|
|
||||||
// Configure AF chain
|
// Configure AF chain
|
||||||
if (postProcEnabled) {
|
if (postProcEnabled) {
|
||||||
// Configure resampler
|
// Configure resampler
|
||||||
afChain.stop();
|
afChain.stop();
|
||||||
double afsr = selectedDemod->getAFSampleRate();
|
resamp.setInSamplerate(selectedDemod->getAFSampleRate());
|
||||||
ctcss.setSamplerate(afsr);
|
|
||||||
resamp.setInSamplerate(afsr);
|
|
||||||
afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
|
||||||
setAudioSampleRate(audioSampleRate);
|
setAudioSampleRate(audioSampleRate);
|
||||||
|
afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
||||||
// Configure the HPF
|
|
||||||
setHighPass(highPass && highPassAllowed);
|
|
||||||
|
|
||||||
// Configure deemphasis
|
// Configure deemphasis
|
||||||
setDeemphasisMode(deempModes[deempId]);
|
setDeemphasisMode(deempModes[deempId]);
|
||||||
@@ -593,32 +489,12 @@ private:
|
|||||||
// Configure resampler
|
// Configure resampler
|
||||||
resamp.setOutSamplerate(audioSampleRate);
|
resamp.setOutSamplerate(audioSampleRate);
|
||||||
|
|
||||||
// Configure the HPF sample rate
|
|
||||||
hpTaps = dsp::taps::highPass(300.0, 100.0, audioSampleRate);
|
|
||||||
hpf.setTaps(hpTaps);
|
|
||||||
|
|
||||||
// Configure deemphasis sample rate
|
// Configure deemphasis sample rate
|
||||||
deemp.setSamplerate(audioSampleRate);
|
deemp.setSamplerate(audioSampleRate);
|
||||||
|
|
||||||
afChain.start();
|
afChain.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHighPass(bool enabled) {
|
|
||||||
// Update the state
|
|
||||||
highPass = enabled;
|
|
||||||
|
|
||||||
// Check if post-processing is enabled and that a demodulator is selected
|
|
||||||
if (!postProcEnabled || !selectedDemod) { return; }
|
|
||||||
|
|
||||||
// Set the state of the HPF in the AF chain
|
|
||||||
afChain.setBlockEnabled(&hpf, enabled, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
|
||||||
|
|
||||||
// Save config
|
|
||||||
config.acquire();
|
|
||||||
config.conf[name][selectedDemod->getName()]["highPass"] = enabled;
|
|
||||||
config.release(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeemphasisMode(DeemphasisMode mode) {
|
void setDeemphasisMode(DeemphasisMode mode) {
|
||||||
deempId = deempModes.valueId(mode);
|
deempId = deempModes.valueId(mode);
|
||||||
if (!postProcEnabled || !selectedDemod) { return; }
|
if (!postProcEnabled || !selectedDemod) { return; }
|
||||||
@@ -646,7 +522,6 @@ private:
|
|||||||
void setNBLevel(float level) {
|
void setNBLevel(float level) {
|
||||||
nbLevel = std::clamp<float>(level, MIN_NB, MAX_NB);
|
nbLevel = std::clamp<float>(level, MIN_NB, MAX_NB);
|
||||||
nb.setLevel(nbLevel);
|
nb.setLevel(nbLevel);
|
||||||
if (!selectedDemod) { return; }
|
|
||||||
|
|
||||||
// Save config
|
// Save config
|
||||||
config.acquire();
|
config.acquire();
|
||||||
@@ -654,59 +529,20 @@ private:
|
|||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSquelchMode(SquelchMode mode) {
|
void setSquelchEnabled(bool enable) {
|
||||||
squelchModeId = squelchModes.valueId(mode);
|
squelchEnabled = enable;
|
||||||
if (!selectedDemod) { return; }
|
if (!selectedDemod) { return; }
|
||||||
|
ifChain.setBlockEnabled(&squelch, squelchEnabled, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
||||||
// Disable all squelch blocks
|
|
||||||
ifChain.disableBlock(&powerSquelch, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
|
||||||
afChain.disableBlock(&ctcss, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
|
||||||
|
|
||||||
// Enable the block depending on the mode
|
|
||||||
switch (mode) {
|
|
||||||
case SQUELCH_MODE_OFF:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_POWER:
|
|
||||||
// Enable the power squelch block
|
|
||||||
ifChain.enableBlock(&powerSquelch, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_SNR:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_CTCSS_MUTE:
|
|
||||||
// Set the required tone and enable the CTCSS squelch block
|
|
||||||
ctcss.setRequiredTone(ctcssTones[ctcssToneId]);
|
|
||||||
afChain.enableBlock(&ctcss, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_CTCSS_DECODE:
|
|
||||||
// Set the required tone to none and enable the CTCSS squelch block
|
|
||||||
ctcss.setRequiredTone(dsp::noise_reduction::CTCSS_TONE_NONE);
|
|
||||||
afChain.enableBlock(&ctcss, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_DCS_MUTE:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQUELCH_MODE_DCS_DECODE:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save config
|
// Save config
|
||||||
config.acquire();
|
config.acquire();
|
||||||
config.conf[name][selectedDemod->getName()]["squelchMode"] = squelchModes.key(squelchModeId);
|
config.conf[name][selectedDemod->getName()]["squelchEnabled"] = squelchEnabled;
|
||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSquelchLevel(float level) {
|
void setSquelchLevel(float level) {
|
||||||
squelchLevel = std::clamp<float>(level, MIN_SQUELCH, MAX_SQUELCH);
|
squelchLevel = std::clamp<float>(level, MIN_SQUELCH, MAX_SQUELCH);
|
||||||
powerSquelch.setLevel(squelchLevel);
|
squelch.setLevel(squelchLevel);
|
||||||
if (!selectedDemod) { return; }
|
|
||||||
|
|
||||||
// Save config
|
// Save config
|
||||||
config.acquire();
|
config.acquire();
|
||||||
@@ -714,24 +550,6 @@ private:
|
|||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCTCSSTone(dsp::noise_reduction::CTCSSTone tone) {
|
|
||||||
// Check for an invalid value
|
|
||||||
if (tone == dsp::noise_reduction::CTCSS_TONE_NONE) { return; }
|
|
||||||
|
|
||||||
// If not in CTCSS mute mode, do nothing
|
|
||||||
if (squelchModes[squelchModeId] != SQUELCH_MODE_CTCSS_MUTE) { return; }
|
|
||||||
|
|
||||||
// Set the tone
|
|
||||||
ctcssToneId = ctcssTones.valueId(tone);
|
|
||||||
ctcss.setRequiredTone(tone);
|
|
||||||
if (!selectedDemod) { return; }
|
|
||||||
|
|
||||||
// Save config
|
|
||||||
config.acquire();
|
|
||||||
config.conf[name][selectedDemod->getName()]["ctcssTone"] = ctcssTones.key(ctcssToneId);
|
|
||||||
config.release(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFMIFNREnabled(bool enabled) {
|
void setFMIFNREnabled(bool enabled) {
|
||||||
FMIFNREnabled = enabled;
|
FMIFNREnabled = enabled;
|
||||||
if (!selectedDemod) { return; }
|
if (!selectedDemod) { return; }
|
||||||
@@ -801,13 +619,13 @@ private:
|
|||||||
if (_this->bandwidthLocked) { return; }
|
if (_this->bandwidthLocked) { return; }
|
||||||
_this->setBandwidth(*_in);
|
_this->setBandwidth(*_in);
|
||||||
}
|
}
|
||||||
else if (code == RADIO_IFACE_CMD_GET_SQUELCH_MODE && out) {
|
else if (code == RADIO_IFACE_CMD_GET_SQUELCH_ENABLED && out) {
|
||||||
SquelchMode* _out = (SquelchMode*)out;
|
bool* _out = (bool*)out;
|
||||||
*_out = _this->squelchModes[_this->squelchModeId];
|
*_out = _this->squelchEnabled;
|
||||||
}
|
}
|
||||||
else if (code == RADIO_IFACE_CMD_SET_SQUELCH_MODE && in && _this->enabled) {
|
else if (code == RADIO_IFACE_CMD_SET_SQUELCH_ENABLED && in && _this->enabled) {
|
||||||
SquelchMode* _in = (SquelchMode*)in;
|
bool* _in = (bool*)in;
|
||||||
_this->setSquelchMode(*_in);
|
_this->setSquelchEnabled(*_in);
|
||||||
}
|
}
|
||||||
else if (code == RADIO_IFACE_CMD_GET_SQUELCH_LEVEL && out) {
|
else if (code == RADIO_IFACE_CMD_GET_SQUELCH_LEVEL && out) {
|
||||||
float* _out = (float*)out;
|
float* _out = (float*)out;
|
||||||
@@ -817,22 +635,6 @@ private:
|
|||||||
float* _in = (float*)in;
|
float* _in = (float*)in;
|
||||||
_this->setSquelchLevel(*_in);
|
_this->setSquelchLevel(*_in);
|
||||||
}
|
}
|
||||||
else if (code == RADIO_IFACE_CMD_GET_CTCSS_TONE && out) {
|
|
||||||
dsp::noise_reduction::CTCSSTone* _out = (dsp::noise_reduction::CTCSSTone*)out;
|
|
||||||
*_out = _this->ctcssTones[_this->ctcssToneId];
|
|
||||||
}
|
|
||||||
else if (code == RADIO_IFACE_CMD_SET_CTCSS_TONE && in && _this->enabled) {
|
|
||||||
dsp::noise_reduction::CTCSSTone* _in = (dsp::noise_reduction::CTCSSTone*)in;
|
|
||||||
_this->setCTCSSTone(*_in);
|
|
||||||
}
|
|
||||||
else if (code == RADIO_IFACE_CMD_GET_HIGHPASS && out) {
|
|
||||||
bool* _out = (bool*)out;
|
|
||||||
*_out = _this->highPass;
|
|
||||||
}
|
|
||||||
else if (code == RADIO_IFACE_CMD_SET_HIGHPASS && in && _this->enabled) {
|
|
||||||
bool* _in = (bool*)in;
|
|
||||||
_this->setHighPass(*_in);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -853,15 +655,12 @@ private:
|
|||||||
dsp::chain<dsp::complex_t> ifChain;
|
dsp::chain<dsp::complex_t> ifChain;
|
||||||
dsp::noise_reduction::NoiseBlanker nb;
|
dsp::noise_reduction::NoiseBlanker nb;
|
||||||
dsp::noise_reduction::FMIF fmnr;
|
dsp::noise_reduction::FMIF fmnr;
|
||||||
dsp::noise_reduction::PowerSquelch powerSquelch;
|
dsp::noise_reduction::Squelch squelch;
|
||||||
|
|
||||||
// Audio chain
|
// Audio chain
|
||||||
dsp::stream<dsp::stereo_t> dummyAudioStream;
|
dsp::stream<dsp::stereo_t> dummyAudioStream;
|
||||||
dsp::chain<dsp::stereo_t> afChain;
|
dsp::chain<dsp::stereo_t> afChain;
|
||||||
dsp::noise_reduction::CTCSSSquelch ctcss;
|
|
||||||
dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
|
dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
|
||||||
dsp::tap<float> hpTaps;
|
|
||||||
dsp::filter::FIR<dsp::stereo_t, float> hpf;
|
|
||||||
dsp::filter::Deemphasis<dsp::stereo_t> deemp;
|
dsp::filter::Deemphasis<dsp::stereo_t> deemp;
|
||||||
|
|
||||||
SinkManager::Stream stream;
|
SinkManager::Stream stream;
|
||||||
@@ -870,8 +669,6 @@ private:
|
|||||||
|
|
||||||
OptionList<std::string, DeemphasisMode> deempModes;
|
OptionList<std::string, DeemphasisMode> deempModes;
|
||||||
OptionList<std::string, IFNRPreset> ifnrPresets;
|
OptionList<std::string, IFNRPreset> ifnrPresets;
|
||||||
OptionList<std::string, SquelchMode> squelchModes;
|
|
||||||
OptionList<int, dsp::noise_reduction::CTCSSTone> ctcssTones;
|
|
||||||
|
|
||||||
double audioSampleRate = 48000.0;
|
double audioSampleRate = 48000.0;
|
||||||
float minBandwidth;
|
float minBandwidth;
|
||||||
@@ -882,13 +679,8 @@ private:
|
|||||||
int selectedDemodID = 1;
|
int selectedDemodID = 1;
|
||||||
bool postProcEnabled;
|
bool postProcEnabled;
|
||||||
|
|
||||||
int squelchModeId = 0;
|
bool squelchEnabled = false;
|
||||||
float squelchLevel;
|
float squelchLevel;
|
||||||
int ctcssToneId = 0;
|
|
||||||
bool squelchAllowed = false;
|
|
||||||
|
|
||||||
bool highPass = false;
|
|
||||||
bool highPassAllowed = false;
|
|
||||||
|
|
||||||
int deempId = 0;
|
int deempId = 0;
|
||||||
bool deempAllowed;
|
bool deempAllowed;
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
|
||||||
project(ryfi_decoder)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c")
|
|
||||||
|
|
||||||
include(${SDRPP_MODULE_CMAKE})
|
|
||||||
|
|
||||||
target_include_directories(ryfi_decoder PRIVATE "src/")
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
#include <imgui.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <core.h>
|
|
||||||
#include <gui/style.h>
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <signal_path/signal_path.h>
|
|
||||||
#include <module.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <dsp/routing/splitter.h>
|
|
||||||
#include <dsp/buffer/reshaper.h>
|
|
||||||
#include <dsp/sink/handler_sink.h>
|
|
||||||
#include <gui/widgets/folder_select.h>
|
|
||||||
#include <gui/widgets/constellation_diagram.h>
|
|
||||||
#include "ryfi/receiver.h"
|
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
|
||||||
|
|
||||||
SDRPP_MOD_INFO{
|
|
||||||
/* Name: */ "ryfi_decoder",
|
|
||||||
/* Description: */ "RyFi decoder for SDR++",
|
|
||||||
/* Author: */ "Ryzerth",
|
|
||||||
/* Version: */ 0, 1, 0,
|
|
||||||
/* Max instances */ -1
|
|
||||||
};
|
|
||||||
|
|
||||||
#define INPUT_BANDWIDTH 600e3
|
|
||||||
#define INPUT_SAMPLE_RATE 1000e3
|
|
||||||
#define INPUT_BAUDRATE 500e3
|
|
||||||
|
|
||||||
#define SYMBOL_DIAG_RATE 30
|
|
||||||
#define SYMBOL_DIAG_COUNT 1024
|
|
||||||
|
|
||||||
class RyFiDecoderModule : public ModuleManager::Instance {
|
|
||||||
public:
|
|
||||||
RyFiDecoderModule(std::string name) {
|
|
||||||
this->name = name;
|
|
||||||
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_BANDWIDTH, INPUT_SAMPLE_RATE, INPUT_BANDWIDTH, INPUT_BANDWIDTH, true);
|
|
||||||
rx.init(vfo->output, INPUT_BAUDRATE, INPUT_SAMPLE_RATE);
|
|
||||||
reshape.init(rx.softOut, SYMBOL_DIAG_COUNT, (INPUT_BAUDRATE / SYMBOL_DIAG_RATE) - SYMBOL_DIAG_COUNT);
|
|
||||||
symSink.init(&reshape.out, symSinkHandler, this);
|
|
||||||
rx.onPacket.bind(&RyFiDecoderModule::packetHandler, this);
|
|
||||||
|
|
||||||
rx.start();
|
|
||||||
reshape.start();
|
|
||||||
symSink.start();
|
|
||||||
|
|
||||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~RyFiDecoderModule() {
|
|
||||||
rx.stop();
|
|
||||||
reshape.stop();
|
|
||||||
symSink.stop();
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
gui::menu.removeEntry(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void postInit() {}
|
|
||||||
|
|
||||||
void enable() {
|
|
||||||
double bw = gui::waterfall.getBandwidth();
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), INPUT_BANDWIDTH, INPUT_SAMPLE_RATE, INPUT_BANDWIDTH, INPUT_BANDWIDTH, true);
|
|
||||||
|
|
||||||
rx.setInput(vfo->output);
|
|
||||||
|
|
||||||
rx.start();
|
|
||||||
reshape.start();
|
|
||||||
symSink.start();
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable() {
|
|
||||||
rx.stop();
|
|
||||||
reshape.stop();
|
|
||||||
symSink.stop();
|
|
||||||
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void packetHandler(ryfi::Packet pkt) {
|
|
||||||
flog::debug("Got a {} byte packet!", pkt.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void menuHandler(void* ctx) {
|
|
||||||
RyFiDecoderModule* _this = (RyFiDecoderModule*)ctx;
|
|
||||||
|
|
||||||
float menuWidth = ImGui::GetContentRegionAvail().x;
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::beginDisabled(); }
|
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(menuWidth);
|
|
||||||
_this->constDiagram.draw();
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::endDisabled(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void symSinkHandler(dsp::complex_t* data, int count, void* ctx) {
|
|
||||||
RyFiDecoderModule* _this = (RyFiDecoderModule*)ctx;
|
|
||||||
|
|
||||||
dsp::complex_t* buf = _this->constDiagram.acquireBuffer();
|
|
||||||
memcpy(buf, data, 1024 * sizeof(dsp::complex_t));
|
|
||||||
_this->constDiagram.releaseBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool enabled = true;
|
|
||||||
|
|
||||||
// DSP Chain
|
|
||||||
VFOManager::VFO* vfo;
|
|
||||||
ryfi::Receiver rx;
|
|
||||||
dsp::buffer::Reshaper<dsp::complex_t> reshape;
|
|
||||||
dsp::sink::Handler<dsp::complex_t> symSink;
|
|
||||||
|
|
||||||
ImGui::ConstellationDiagram constDiagram;
|
|
||||||
};
|
|
||||||
|
|
||||||
MOD_EXPORT void _INIT_() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
|
|
||||||
return new RyFiDecoderModule(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
|
|
||||||
delete (RyFiDecoderModule*)instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _END_() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#include "conv_codec.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
ConvEncoder::ConvEncoder(dsp::stream<uint8_t>* in) {
|
|
||||||
// Create the convolutional encoder instance
|
|
||||||
conv = correct_convolutional_create(2, 7, correct_conv_r12_7_polynomial);
|
|
||||||
|
|
||||||
// Init the base class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConvEncoder::~ConvEncoder() {
|
|
||||||
// Destroy the convolutional encoder instance
|
|
||||||
correct_convolutional_destroy(conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConvEncoder::encode(const uint8_t* in, uint8_t* out, int count) {
|
|
||||||
// Run convolutional encoder on the data
|
|
||||||
return correct_convolutional_encode(conv, in, count, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConvEncoder::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
count = encode(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConvDecoder::ConvDecoder(dsp::stream<dsp::complex_t>* in) {
|
|
||||||
// Create the convolutional encoder instance
|
|
||||||
conv = correct_convolutional_create(2, 7, correct_conv_r12_7_polynomial);
|
|
||||||
|
|
||||||
// Allocate the soft symbol buffer
|
|
||||||
soft = dsp::buffer::alloc<uint8_t>(STREAM_BUFFER_SIZE);
|
|
||||||
|
|
||||||
// Init the base class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConvDecoder::~ConvDecoder() {
|
|
||||||
// Destroy the convolutional encoder instance
|
|
||||||
correct_convolutional_destroy(conv);
|
|
||||||
|
|
||||||
// Free the soft symbol buffer
|
|
||||||
dsp::buffer::free(soft);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConvDecoder::decode(const dsp::complex_t* in, uint8_t* out, int count) {
|
|
||||||
// Convert to uint8
|
|
||||||
const float* _in = (const float*)in;
|
|
||||||
count *= 2;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
soft[i] = std::clamp<int>((_in[i] * 127.0f) + 128.0f, 0, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run convolutional decoder on the data
|
|
||||||
return correct_convolutional_decode_soft(conv, soft, count, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConvDecoder::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
count = decode(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "dsp/processor.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "correct.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
/**
|
|
||||||
* RyFi Convolutional Encoder.
|
|
||||||
*/
|
|
||||||
class ConvEncoder : public dsp::Processor<uint8_t, uint8_t> {
|
|
||||||
using base_type = dsp::Processor<uint8_t, uint8_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a convolutional encoder specifying an input stream.
|
|
||||||
* @param in Input stream.
|
|
||||||
*/
|
|
||||||
ConvEncoder(dsp::stream<uint8_t>* in = NULL);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~ConvEncoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode data.
|
|
||||||
* @param in Input bytes.
|
|
||||||
* @param out Output bits.
|
|
||||||
* @param count Number of input bytes.
|
|
||||||
* @return Number of output bits.
|
|
||||||
*/
|
|
||||||
int encode(const uint8_t* in, uint8_t* out, int count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
correct_convolutional* conv;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RyFi Convolutional Decoder.
|
|
||||||
*/
|
|
||||||
class ConvDecoder : public dsp::Processor<dsp::complex_t, uint8_t> {
|
|
||||||
using base_type = dsp::Processor<dsp::complex_t, uint8_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a convolutional encoder specifying an input stream.
|
|
||||||
* @param in Input stream.
|
|
||||||
*/
|
|
||||||
ConvDecoder(dsp::stream<dsp::complex_t>* in = NULL);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~ConvDecoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode soft symbols.
|
|
||||||
* @param in Input soft symbols.
|
|
||||||
* @param out Output bytes.
|
|
||||||
* @param count Number of input bytes.
|
|
||||||
* @return Number of output bits.
|
|
||||||
*/
|
|
||||||
int decode(const dsp::complex_t* in, uint8_t* out, int count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
correct_convolutional* conv;
|
|
||||||
uint8_t* soft = NULL;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#include "frame.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
int Frame::serialize(uint8_t* bytes) const {
|
|
||||||
// Write the counter
|
|
||||||
bytes[0] = (counter >> 8) & 0xFF;
|
|
||||||
bytes[1] = counter & 0xFF;
|
|
||||||
|
|
||||||
// Write the first packet pointer
|
|
||||||
bytes[2] = (firstPacket >> 8) & 0xFF;
|
|
||||||
bytes[3] = firstPacket & 0xFF;
|
|
||||||
|
|
||||||
// Write the last packet pointer
|
|
||||||
bytes[4] = (lastPacket >> 8) & 0xFF;
|
|
||||||
bytes[5] = lastPacket & 0xFF;
|
|
||||||
|
|
||||||
// Write the data
|
|
||||||
memcpy(&bytes[6], content, FRAME_DATA_SIZE);
|
|
||||||
|
|
||||||
// Return the length of a serialized frame
|
|
||||||
return FRAME_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Frame::deserialize(const uint8_t* bytes, Frame& frame) {
|
|
||||||
// Read the counter
|
|
||||||
frame.counter = (((uint16_t)bytes[0]) << 8) | ((uint16_t)bytes[1]);
|
|
||||||
|
|
||||||
// Read the first packet pointer
|
|
||||||
frame.firstPacket = (((uint16_t)bytes[2]) << 8) | ((uint16_t)bytes[3]);
|
|
||||||
|
|
||||||
// Read the last packet pointer
|
|
||||||
frame.lastPacket = (((uint16_t)bytes[4]) << 8) | ((uint16_t)bytes[5]);
|
|
||||||
|
|
||||||
// Read the data
|
|
||||||
memcpy(frame.content, &bytes[6], FRAME_DATA_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "rs_codec.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
enum PacketOffset {
|
|
||||||
PKT_OFFS_NONE = 0xFFFF
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Frame {
|
|
||||||
/**
|
|
||||||
* Serialize the frame to bytes.
|
|
||||||
* @param bytes Buffer to write the serialized frame to.
|
|
||||||
*/
|
|
||||||
int serialize(uint8_t* bytes) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserialize a frame from bytes.
|
|
||||||
* @param bytes Buffer to deserialize the frame from.
|
|
||||||
* @param frame Object that will contain the deserialize frame.
|
|
||||||
*/
|
|
||||||
static void deserialize(const uint8_t* bytes, Frame& frame);
|
|
||||||
|
|
||||||
// Size of a serialized frame
|
|
||||||
static inline const int FRAME_SIZE = RS_BLOCK_DEC_SIZE*RS_BLOCK_COUNT;
|
|
||||||
|
|
||||||
// Size of the data area of the frame
|
|
||||||
static inline const int FRAME_DATA_SIZE = FRAME_SIZE - 6;
|
|
||||||
|
|
||||||
// Steadily increasing counter.
|
|
||||||
uint16_t counter = 0;
|
|
||||||
|
|
||||||
// Byte offset of the first packet in the frame.
|
|
||||||
uint16_t firstPacket = 0;
|
|
||||||
|
|
||||||
// Byte offset of the last packet in the frame.
|
|
||||||
uint16_t lastPacket = 0;
|
|
||||||
|
|
||||||
// Data area of the frame.
|
|
||||||
uint8_t content[FRAME_DATA_SIZE];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
#include "framing.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
dsp::complex_t QPSK_SYMBOLS[4] = {
|
|
||||||
{ -0.070710678118f, -0.070710678118f },
|
|
||||||
{ -0.070710678118f, 0.070710678118f },
|
|
||||||
{ 0.070710678118f, -0.070710678118f },
|
|
||||||
{ 0.070710678118f, 0.070710678118f },
|
|
||||||
};
|
|
||||||
|
|
||||||
Framer::Framer(dsp::stream<uint8_t>* in) {
|
|
||||||
// Generate the sync symbols
|
|
||||||
int k = 0;
|
|
||||||
for (int i = 62; i >= 0; i -= 2) {
|
|
||||||
syncSyms[k++] = QPSK_SYMBOLS[(SYNC_WORD >> i) & 0b11];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize base class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Framer::encode(const uint8_t* in, dsp::complex_t* out, int count) {
|
|
||||||
// Copy sync symbols
|
|
||||||
memcpy(out, syncSyms, SYNC_SYMS*sizeof(dsp::complex_t));
|
|
||||||
|
|
||||||
// Modulate the rest of the bits
|
|
||||||
dsp::complex_t* dataOut = &out[SYNC_SYMS];
|
|
||||||
int dataSyms = count / 2;
|
|
||||||
for (int i = 0; i < dataSyms; i++) {
|
|
||||||
uint8_t bits = (in[i >> 2] >> (6 - 2*(i & 0b11))) & 0b11;
|
|
||||||
dataOut[i] = QPSK_SYMBOLS[bits];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute and return the total number of symbols
|
|
||||||
return SYNC_SYMS + dataSyms;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Framer::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
count = encode(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
Deframer::Deframer(dsp::stream<dsp::complex_t> *in) {
|
|
||||||
// Compute sync word rotations
|
|
||||||
// 0: 00 01 11 10
|
|
||||||
// 90: 10 00 01 11
|
|
||||||
// 180: 11 10 00 01
|
|
||||||
// 270: 01 11 10 00
|
|
||||||
|
|
||||||
// For 0 and 180 it's the sync and its complement
|
|
||||||
syncRots[ROT_0_DEG] = SYNC_WORD;
|
|
||||||
syncRots[ROT_180_DEG] = ~SYNC_WORD;
|
|
||||||
|
|
||||||
// For 90 and 270 its the quadrature and its complement
|
|
||||||
uint64_t quad;
|
|
||||||
for (int i = 62; i >= 0; i -= 2) {
|
|
||||||
// Get the symbol
|
|
||||||
uint8_t sym = (SYNC_WORD >> i) & 0b11;
|
|
||||||
|
|
||||||
// Rotate it 90 degrees
|
|
||||||
uint8_t rsym;
|
|
||||||
switch (sym) {
|
|
||||||
case 0b00: rsym = 0b10; break;
|
|
||||||
case 0b01: rsym = 0b00; break;
|
|
||||||
case 0b11: rsym = 0b01; break;
|
|
||||||
case 0b10: rsym = 0b11; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push it into the quadrature
|
|
||||||
quad = (quad << 2) | rsym;
|
|
||||||
}
|
|
||||||
syncRots[ROT_90_DEG] = quad;
|
|
||||||
syncRots[ROT_270_DEG] = ~quad;
|
|
||||||
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Deframer::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
dsp::complex_t* in = base_type::_in->readBuf;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (recv) {
|
|
||||||
// Copy the symbol to the output and rotate it approprieate
|
|
||||||
base_type::out.writeBuf[outCount++] = in[i] * symRot;
|
|
||||||
|
|
||||||
// Check if we're done receiving the frame, send it out
|
|
||||||
if (!(--recv)) {
|
|
||||||
if (!base_type::out.swap(outCount)) {
|
|
||||||
base_type::_in->flush();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Get the raw symbol
|
|
||||||
dsp::complex_t fsym = in[i];
|
|
||||||
|
|
||||||
// Decode the symbol
|
|
||||||
uint8_t sym = ((fsym.re > 0) ? 0b10 : 0b00) | ((fsym.im > 0) ? 0b01 : 0b00);
|
|
||||||
|
|
||||||
// Push it to the shift register
|
|
||||||
shift = (shift << 2) | sym;
|
|
||||||
|
|
||||||
// Find the rotation starting with the last known one
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
// Get the test rotation
|
|
||||||
int testRot = (knownRot+i) & 0b11;
|
|
||||||
|
|
||||||
// Check if the hamming distance is close enough
|
|
||||||
int dist;
|
|
||||||
if (distance(shift, syncRots[testRot]) < 6) {
|
|
||||||
// Save the new rotation
|
|
||||||
knownRot = testRot;
|
|
||||||
|
|
||||||
// Start reading in symbols for the frame
|
|
||||||
symRot = symRots[knownRot];
|
|
||||||
recv = 8168; // TODO: Don't hardcode!
|
|
||||||
outCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "dsp/processor.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
// Synchronization word.
|
|
||||||
inline const uint64_t SYNC_WORD = 0x341CC540819D8963;
|
|
||||||
|
|
||||||
// Number of synchronization bits.
|
|
||||||
inline const int SYNC_BITS = 64;
|
|
||||||
|
|
||||||
// Number of synchronization symbols.
|
|
||||||
inline const int SYNC_SYMS = SYNC_BITS / 2;
|
|
||||||
|
|
||||||
// Possible constellation rotations
|
|
||||||
enum {
|
|
||||||
ROT_0_DEG = 0,
|
|
||||||
ROT_90_DEG = 1,
|
|
||||||
ROT_180_DEG = 2,
|
|
||||||
ROT_270_DEG = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RyFi Framer.
|
|
||||||
*/
|
|
||||||
class Framer : public dsp::Processor<uint8_t, dsp::complex_t> {
|
|
||||||
using base_type = dsp::Processor<uint8_t, dsp::complex_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a framer specifying an input stream.
|
|
||||||
* @param in Input stream.
|
|
||||||
*/
|
|
||||||
Framer(dsp::stream<uint8_t>* in = NULL);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a frame to symbols adding a sync word.
|
|
||||||
*/
|
|
||||||
int encode(const uint8_t* in, dsp::complex_t* out, int count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
dsp::complex_t syncSyms[SYNC_SYMS];
|
|
||||||
};
|
|
||||||
|
|
||||||
class Deframer : public dsp::Processor<dsp::complex_t, dsp::complex_t> {
|
|
||||||
using base_type = dsp::Processor<dsp::complex_t, dsp::complex_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a deframer specifying an input stream.
|
|
||||||
* @param in Input stream.
|
|
||||||
*/
|
|
||||||
Deframer(dsp::stream<dsp::complex_t> *in = NULL);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
inline static constexpr int distance(uint64_t a, uint64_t b) {
|
|
||||||
int dist = 0;
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
dist += ((a & 1) != (b & 1));
|
|
||||||
a >>= 1;
|
|
||||||
b >>= 1;
|
|
||||||
}
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frame reading counters
|
|
||||||
int recv = 0;
|
|
||||||
int outCount = 0;
|
|
||||||
|
|
||||||
// Rotation handling
|
|
||||||
int knownRot = 0;
|
|
||||||
uint64_t syncRots[4];
|
|
||||||
dsp::complex_t symRot;
|
|
||||||
const dsp::complex_t symRots[4] = {
|
|
||||||
{ 1.0f, 0.0f }, // 0 deg
|
|
||||||
{ 0.0f, -1.0f }, // 90 deg
|
|
||||||
{ -1.0f, 0.0f }, // 180 deg
|
|
||||||
{ 0.0f, 1.0f }, // 270 deg
|
|
||||||
};
|
|
||||||
|
|
||||||
// Shift register
|
|
||||||
uint64_t shift;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
#include "packet.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
Packet::Packet() {}
|
|
||||||
|
|
||||||
Packet::Packet(uint8_t* content, int size) {
|
|
||||||
// Check that the size isn't too large
|
|
||||||
if (size > MAX_CONTENT_SIZE) {
|
|
||||||
throw std::runtime_error("Content size is too large to fit in a packet");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Allocate the buffer
|
|
||||||
allocate(size);
|
|
||||||
|
|
||||||
// Copy over the content
|
|
||||||
memcpy(_content, content, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::Packet(const Packet& b) {
|
|
||||||
// Reallocate the buffer
|
|
||||||
allocate(b._size);
|
|
||||||
|
|
||||||
// Copy over the content
|
|
||||||
memcpy(_content, b._content, b._size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::Packet(Packet&& b) {
|
|
||||||
// Move members
|
|
||||||
_content = b._content;
|
|
||||||
_size = b._size;
|
|
||||||
|
|
||||||
// Destroy old object
|
|
||||||
b._content = NULL;
|
|
||||||
b._size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::~Packet() {
|
|
||||||
// Delete the content
|
|
||||||
if (_content) { delete[] _content; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet& Packet::operator=(const Packet& b) {
|
|
||||||
// Reallocate the buffer
|
|
||||||
allocate(b._size);
|
|
||||||
|
|
||||||
// Copy over the content
|
|
||||||
memcpy(_content, b._content, b._size);
|
|
||||||
|
|
||||||
// Return self
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet& Packet::operator=(Packet&& b) {
|
|
||||||
// Move members
|
|
||||||
_content = b._content;
|
|
||||||
_size = b._size;
|
|
||||||
|
|
||||||
// Destroy old object
|
|
||||||
b._content = NULL;
|
|
||||||
b._size = 0;
|
|
||||||
|
|
||||||
// Return self
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::operator bool() const {
|
|
||||||
return _size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Packet::size() const {
|
|
||||||
// Return the size
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* Packet::data() const {
|
|
||||||
// Return the size
|
|
||||||
return _content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::setContent(uint8_t* content, int size) {
|
|
||||||
// Check that the size isn't too large
|
|
||||||
if (size > MAX_CONTENT_SIZE) {
|
|
||||||
throw std::runtime_error("Content size is too large to fit in a packet");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reallocate the buffer
|
|
||||||
allocate(size);
|
|
||||||
|
|
||||||
// Copy over the content
|
|
||||||
memcpy(_content, content, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Packet::serializedSize() const {
|
|
||||||
// Two size bytes + Size of the content
|
|
||||||
return _size + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Packet::serialize(uint8_t* bytes) const {
|
|
||||||
// Write the size in big-endian
|
|
||||||
bytes[0] = (_size >> 8) & 0xFF;
|
|
||||||
bytes[1] = _size & 0xFF;
|
|
||||||
|
|
||||||
// Copy the content of the packet
|
|
||||||
memcpy(&bytes[2], _content, _size);
|
|
||||||
|
|
||||||
// Return the serialized size
|
|
||||||
return serializedSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::allocate(int newSize) {
|
|
||||||
// If the size hasn't changed, do nothing
|
|
||||||
if (newSize == _size) { return; }
|
|
||||||
|
|
||||||
// Free the old buffer
|
|
||||||
if (_content) { delete[] _content; };
|
|
||||||
|
|
||||||
// Update the size
|
|
||||||
_size = newSize;
|
|
||||||
|
|
||||||
// Allocate the buffer
|
|
||||||
_content = new uint8_t[newSize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
/**
|
|
||||||
* RyFi Protocol Packet.
|
|
||||||
*/
|
|
||||||
class Packet {
|
|
||||||
public:
|
|
||||||
// Default constructor
|
|
||||||
Packet();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a packet from its content.
|
|
||||||
* @param content Content of the packet.
|
|
||||||
* @param size Number of bytes of content.
|
|
||||||
*/
|
|
||||||
Packet(uint8_t* content, int size);
|
|
||||||
|
|
||||||
// Copy constructor
|
|
||||||
Packet(const Packet& b);
|
|
||||||
|
|
||||||
// Move constructor
|
|
||||||
Packet(Packet&& b);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Packet();
|
|
||||||
|
|
||||||
// Copy assignment operator
|
|
||||||
Packet& operator=(const Packet& b);
|
|
||||||
|
|
||||||
// Move assignment operator
|
|
||||||
Packet& operator=(Packet&& b);
|
|
||||||
|
|
||||||
// Cast to bool operator
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the size of the content of the packet.
|
|
||||||
* @return Size of the content of the packet.
|
|
||||||
*/
|
|
||||||
int size() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the content of the packet. The pointer is only valid until reallocation or deletion.
|
|
||||||
* @return Content of the packet.
|
|
||||||
*/
|
|
||||||
const uint8_t* data() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the content of the packet.
|
|
||||||
* @param content Content of the packet.
|
|
||||||
* @param size Number of bytes of content.
|
|
||||||
*/
|
|
||||||
void setContent(uint8_t* content, int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the size of the serialized packet.
|
|
||||||
* @return Size of the serialized packet.
|
|
||||||
*/
|
|
||||||
int serializedSize() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize the packet to bytes.
|
|
||||||
* @param bytes Buffer to which to write the serialized packet.
|
|
||||||
* @return Size of the serialized packet.
|
|
||||||
*/
|
|
||||||
int serialize(uint8_t* bytes) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserialize a packet from bytes.
|
|
||||||
* TODO
|
|
||||||
*/
|
|
||||||
static bool deserialize(uint8_t* bytes, int size, Packet& pkt);
|
|
||||||
|
|
||||||
// Maximum size of the content of the packet.
|
|
||||||
static inline const int MAX_CONTENT_SIZE = 0xFFFF;
|
|
||||||
|
|
||||||
// Maximum size of the serialized packet.
|
|
||||||
static inline const int MAX_SERIALIZED_SIZE = MAX_CONTENT_SIZE + 2;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void allocate(int newSize);
|
|
||||||
|
|
||||||
uint8_t* _content = NULL;
|
|
||||||
int _size = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
#include "receiver.h"
|
|
||||||
|
|
||||||
#include "utils/flog.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
Receiver::Receiver() {}
|
|
||||||
|
|
||||||
Receiver::Receiver(dsp::stream<dsp::complex_t>* in, double baudrate, double samplerate) {
|
|
||||||
init(in, baudrate, samplerate);
|
|
||||||
}
|
|
||||||
|
|
||||||
Receiver::~Receiver() {
|
|
||||||
// Stop everything
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::init(dsp::stream<dsp::complex_t>* in, double baudrate, double samplerate) {
|
|
||||||
// Initialize the DSP
|
|
||||||
demod.init(in, baudrate, samplerate, 31, 0.6, 0.1f, 0.005f, 1e-6, 0.01);
|
|
||||||
doubler.init(&demod.out);
|
|
||||||
softOut = &doubler.outA;
|
|
||||||
deframer.setInput(&doubler.outB);
|
|
||||||
conv.setInput(&deframer.out);
|
|
||||||
rs.setInput(&conv.out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::setInput(dsp::stream<dsp::complex_t>* in) {
|
|
||||||
demod.setInput(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::start() {
|
|
||||||
// Do nothing if already running
|
|
||||||
if (running) { return; }
|
|
||||||
|
|
||||||
// Start the worker thread
|
|
||||||
workerThread = std::thread(&Receiver::worker, this);
|
|
||||||
|
|
||||||
// Start the DSP
|
|
||||||
demod.start();
|
|
||||||
doubler.start();
|
|
||||||
deframer.start();
|
|
||||||
conv.start();
|
|
||||||
rs.start();
|
|
||||||
|
|
||||||
// Update the running state
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::stop() {
|
|
||||||
// Do nothing if not running
|
|
||||||
if (!running) { return; }
|
|
||||||
|
|
||||||
// Stop the worker thread
|
|
||||||
rs.out.stopReader();
|
|
||||||
if (workerThread.joinable()) { workerThread.join(); }
|
|
||||||
rs.out.clearReadStop();
|
|
||||||
|
|
||||||
// Stop the DSP
|
|
||||||
demod.stop();
|
|
||||||
doubler.stop();
|
|
||||||
deframer.stop();
|
|
||||||
conv.stop();
|
|
||||||
rs.stop();
|
|
||||||
|
|
||||||
// Update the running state
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::worker() {
|
|
||||||
Frame frame;
|
|
||||||
uint16_t lastCounter = 0;
|
|
||||||
uint8_t* pktBuffer = new uint8_t[Packet::MAX_CONTENT_SIZE];
|
|
||||||
int pktExpected = 0;
|
|
||||||
int pktRead = 0;
|
|
||||||
int valid = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// Read a frame
|
|
||||||
int count = rs.out.read();
|
|
||||||
if (count <= 0) { break; }
|
|
||||||
|
|
||||||
// Deserialize the frame
|
|
||||||
Frame::deserialize(rs.out.readBuf, frame);
|
|
||||||
valid++;
|
|
||||||
|
|
||||||
// Flush the stream
|
|
||||||
rs.out.flush();
|
|
||||||
|
|
||||||
//flog::info("Frame[{}]: FirstPacket={}, LastPacket={}", frame.counter, frame.firstPacket, frame.lastPacket);
|
|
||||||
|
|
||||||
// Compute the expected frame counter
|
|
||||||
uint16_t expectedCounter = lastCounter + 1;
|
|
||||||
lastCounter = frame.counter;
|
|
||||||
|
|
||||||
// If the frames aren't consecutive
|
|
||||||
int frameRead = 0;
|
|
||||||
if (frame.counter != expectedCounter) {
|
|
||||||
flog::warn("Lost at least {} frames after {} valid frames", ((int)frame.counter - (int)expectedCounter + 0x10000) % 0x10000, valid);
|
|
||||||
|
|
||||||
// Cancel the partial packet if there was one
|
|
||||||
pktExpected = 0;
|
|
||||||
pktRead = 0;
|
|
||||||
valid = 1;
|
|
||||||
|
|
||||||
// If this frame is not an idle frame or continuation frame
|
|
||||||
if (frame.firstPacket != PKT_OFFS_NONE) {
|
|
||||||
// If the offset of the first packet is not plausible
|
|
||||||
if (frame.firstPacket > Frame::FRAME_DATA_SIZE-2) {
|
|
||||||
flog::warn("Packet had non-plausible offset: {}", frameRead);
|
|
||||||
|
|
||||||
// Skip the frame
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip to the end of the packet
|
|
||||||
frameRead = frame.firstPacket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no partial packet and the frame doesn't contain a packet start, skip it
|
|
||||||
if (!pktExpected && frame.firstPacket == PKT_OFFS_NONE) { continue; }
|
|
||||||
|
|
||||||
// Extract packets from the frame
|
|
||||||
bool firstPacket = true;
|
|
||||||
bool lastPacket = false;
|
|
||||||
while (frameRead < Frame::FRAME_DATA_SIZE) {
|
|
||||||
// If there is a partial packet read as much as possible from it
|
|
||||||
if (pktExpected) {
|
|
||||||
// Compute how many bytes of the packet are available in the frame
|
|
||||||
int readable = std::min<int>(pktExpected - pktRead, Frame::FRAME_DATA_SIZE - frameRead);
|
|
||||||
//flog::debug("Reading {} bytes", readable);
|
|
||||||
|
|
||||||
// Write them to the packet
|
|
||||||
memcpy(&pktBuffer[pktRead], &frame.content[frameRead], readable);
|
|
||||||
pktRead += readable;
|
|
||||||
frameRead += readable;
|
|
||||||
|
|
||||||
// If the packet is read entirely
|
|
||||||
if (pktRead >= pktExpected) {
|
|
||||||
// Create the packet object
|
|
||||||
Packet pkt(pktBuffer, pktExpected);
|
|
||||||
|
|
||||||
// Send off the packet
|
|
||||||
onPacket(pkt);
|
|
||||||
|
|
||||||
// Prepare for the next packet
|
|
||||||
pktRead = 0;
|
|
||||||
pktExpected = 0;
|
|
||||||
|
|
||||||
// If this was the last packet of the frame
|
|
||||||
if (lastPacket || frame.firstPacket == PKT_OFFS_NONE) {
|
|
||||||
// Skip the rest of the frame
|
|
||||||
frameRead = Frame::FRAME_DATA_SIZE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go to next packet
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the packet offset is not plausible
|
|
||||||
if (Frame::FRAME_DATA_SIZE - frameRead < 2) {
|
|
||||||
flog::warn("Packet had non-plausible offset: {}", frameRead);
|
|
||||||
|
|
||||||
// Skip the rest of the frame and the packet
|
|
||||||
frameRead = Frame::FRAME_DATA_SIZE;
|
|
||||||
pktExpected = 0;
|
|
||||||
pktRead = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is the first packet, use the frame info to skip possible left over data
|
|
||||||
if (firstPacket) {
|
|
||||||
frameRead = frame.firstPacket;
|
|
||||||
firstPacket = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is the last packet
|
|
||||||
lastPacket = (frameRead == frame.lastPacket);
|
|
||||||
|
|
||||||
// Parse the packet size
|
|
||||||
pktExpected = ((uint16_t)frame.content[frameRead]) << 8;
|
|
||||||
pktExpected |= (uint16_t)frame.content[frameRead+1];
|
|
||||||
//flog::debug("Starting to read a {} byte packet at offset {}", pktExpected, frameRead);
|
|
||||||
|
|
||||||
// Skip to the packet content
|
|
||||||
frameRead += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] pktBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "utils/new_event.h"
|
|
||||||
#include "dsp/demod/psk.h"
|
|
||||||
#include "dsp/routing/doubler.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "frame.h"
|
|
||||||
#include "rs_codec.h"
|
|
||||||
#include "conv_codec.h"
|
|
||||||
#include "framing.h"
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
class Receiver {
|
|
||||||
public:
|
|
||||||
Receiver();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a transmitter.
|
|
||||||
* @param in Baseband input.
|
|
||||||
* @param baudrate Baudrate to use over the air.
|
|
||||||
* @param samplerate Samplerate of the baseband.
|
|
||||||
*/
|
|
||||||
Receiver(dsp::stream<dsp::complex_t>* in, double baudrate, double samplerate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a transmitter.
|
|
||||||
* @param in Baseband input.
|
|
||||||
* @param baudrate Baudrate to use over the air.
|
|
||||||
* @param samplerate Samplerate of the baseband.
|
|
||||||
*/
|
|
||||||
void init(dsp::stream<dsp::complex_t>* in, double baudrate, double samplerate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the input stream.
|
|
||||||
* @param in Baseband input.
|
|
||||||
*/
|
|
||||||
void setInput(dsp::stream<dsp::complex_t>* in);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Receiver();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the transmitter's DSP.
|
|
||||||
*/
|
|
||||||
void start();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the transmitter's DSP.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
dsp::stream<dsp::complex_t>* softOut;
|
|
||||||
|
|
||||||
NewEvent<Packet> onPacket;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void worker();
|
|
||||||
|
|
||||||
// DSP
|
|
||||||
dsp::demod::PSK<4> demod;
|
|
||||||
dsp::routing::Doubler<dsp::complex_t> doubler;
|
|
||||||
Deframer deframer;
|
|
||||||
ConvDecoder conv;
|
|
||||||
RSDecoder rs;
|
|
||||||
|
|
||||||
bool running = false;
|
|
||||||
std::thread workerThread;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
#include "rs_codec.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
RSEncoder::RSEncoder(dsp::stream<uint8_t>* in) {
|
|
||||||
// Create the convolutional encoder instance
|
|
||||||
rs = correct_reed_solomon_create(correct_rs_primitive_polynomial_ccsds, 1, 1, 32);
|
|
||||||
|
|
||||||
// Init the base class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
RSEncoder::~RSEncoder() {
|
|
||||||
// Destroy the convolutional encoder instance
|
|
||||||
correct_reed_solomon_destroy(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSEncoder::encode(const uint8_t* in, uint8_t* out, int count) {
|
|
||||||
// Check the size
|
|
||||||
assert(count == RS_BLOCK_COUNT*RS_BLOCK_DEC_SIZE);
|
|
||||||
|
|
||||||
// Go through each block
|
|
||||||
uint8_t block[RS_BLOCK_ENC_SIZE];
|
|
||||||
for (int i = 0; i < RS_BLOCK_COUNT; i++) {
|
|
||||||
// Encode block
|
|
||||||
correct_reed_solomon_encode(rs, &in[i*RS_BLOCK_DEC_SIZE], RS_BLOCK_DEC_SIZE, block);
|
|
||||||
|
|
||||||
// Interleave into the frame
|
|
||||||
int k = 0;
|
|
||||||
for (int j = i; j < RS_BLOCK_ENC_SIZE*RS_BLOCK_COUNT; j += RS_BLOCK_COUNT) {
|
|
||||||
out[j] = block[k++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scramble
|
|
||||||
for (int i = 0; i < RS_BLOCK_COUNT*RS_BLOCK_ENC_SIZE; i++) {
|
|
||||||
out[i] ^= RS_SCRAMBLER_SEQ[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return RS_BLOCK_COUNT*RS_BLOCK_ENC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSEncoder::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
count = encode(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (!out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
RSDecoder::RSDecoder(dsp::stream<uint8_t>* in) {
|
|
||||||
// Create the convolutional encoder instance
|
|
||||||
rs = correct_reed_solomon_create(correct_rs_primitive_polynomial_ccsds, 1, 1, 32);
|
|
||||||
|
|
||||||
// Init the base class
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
RSDecoder::~RSDecoder() {
|
|
||||||
// Destroy the convolutional encoder instance
|
|
||||||
correct_reed_solomon_destroy(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSDecoder::decode(uint8_t* in, uint8_t* out, int count) {
|
|
||||||
// Check the size
|
|
||||||
assert(count == RS_BLOCK_COUNT*RS_BLOCK_ENC_SIZE);
|
|
||||||
|
|
||||||
// Descramble (TODO: Don't do it in-place)
|
|
||||||
for (int i = 0; i < RS_BLOCK_COUNT*RS_BLOCK_ENC_SIZE; i++) {
|
|
||||||
in[i] ^= RS_SCRAMBLER_SEQ[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each block
|
|
||||||
uint8_t block[RS_BLOCK_ENC_SIZE];
|
|
||||||
for (int i = 0; i < RS_BLOCK_COUNT; i++) {
|
|
||||||
// Deinterleave out of the frame
|
|
||||||
int k = 0;
|
|
||||||
for (int j = i; j < count; j += RS_BLOCK_COUNT) {
|
|
||||||
block[k++] = in[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode block and return if decoding fails
|
|
||||||
int res = correct_reed_solomon_decode(rs, block, RS_BLOCK_ENC_SIZE, &out[i*RS_BLOCK_DEC_SIZE]);
|
|
||||||
if (res < 0) { return 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return RS_BLOCK_COUNT*RS_BLOCK_DEC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSDecoder::run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
count = decode(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (count && !out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t RS_SCRAMBLER_SEQ[RS_BLOCK_ENC_SIZE*RS_BLOCK_COUNT] = {
|
|
||||||
0x75, 0x05, 0x7C, 0xCE, 0xF1, 0xD0, 0x6C, 0xF6, 0xFA, 0x65, 0xF6, 0xFC, 0xE0, 0x0A, 0x82, 0x17,
|
|
||||||
0x6C, 0xBE, 0x76, 0xA0, 0xD6, 0x46, 0x12, 0x2E, 0xDE, 0xB5, 0xF7, 0xAD, 0xCB, 0x51, 0x63, 0x47,
|
|
||||||
0x27, 0x30, 0x7E, 0x43, 0xD1, 0xA1, 0xCB, 0x10, 0x08, 0x49, 0xDF, 0x86, 0xD4, 0xC4, 0xD7, 0x3C,
|
|
||||||
0x6D, 0x03, 0x07, 0x37, 0x5B, 0xB3, 0xCD, 0x79, 0x6F, 0x1E, 0xBA, 0xC5, 0x6E, 0xC3, 0x8C, 0x7A,
|
|
||||||
0x25, 0x99, 0x61, 0x54, 0x5A, 0x96, 0x57, 0x9B, 0xE0, 0x60, 0x5B, 0x09, 0x6D, 0x8B, 0x2D, 0x9D,
|
|
||||||
0x15, 0x9D, 0x0E, 0xBF, 0x57, 0xFB, 0x9C, 0x49, 0x82, 0x2C, 0x48, 0x59, 0x92, 0x47, 0x79, 0x17,
|
|
||||||
0x16, 0x74, 0xEA, 0xEA, 0xBB, 0xC5, 0x72, 0x32, 0x17, 0xD1, 0xB3, 0xDE, 0xEB, 0x15, 0xC7, 0x55,
|
|
||||||
0x8A, 0xF2, 0x88, 0xC2, 0x33, 0xA6, 0x17, 0x8B, 0xD4, 0x77, 0x22, 0x00, 0x63, 0x47, 0x45, 0x5F,
|
|
||||||
0x36, 0x35, 0x58, 0x8B, 0x88, 0xEC, 0xCA, 0xC4, 0x60, 0x53, 0x9E, 0xBD, 0xB2, 0xF5, 0x51, 0x46,
|
|
||||||
0x34, 0x9A, 0x07, 0x25, 0x3F, 0xF5, 0x65, 0x63, 0x77, 0x3C, 0x5A, 0xFA, 0x4E, 0x0C, 0xF7, 0x1B,
|
|
||||||
0x82, 0xAB, 0x73, 0x06, 0x7F, 0xB7, 0xC6, 0x6B, 0xBF, 0xB1, 0x46, 0xF3, 0x01, 0x91, 0xB1, 0xFF,
|
|
||||||
0x5C, 0x6F, 0xF9, 0x43, 0x0E, 0x6A, 0x70, 0x89, 0x0B, 0xEA, 0x8C, 0xD4, 0x1B, 0x51, 0x01, 0x31,
|
|
||||||
0x71, 0x2E, 0xDF, 0x24, 0xC1, 0xD5, 0xDB, 0x0E, 0xF5, 0xEB, 0x78, 0x79, 0x39, 0x5B, 0xAD, 0xC3,
|
|
||||||
0xA9, 0xA6, 0x60, 0x30, 0xA2, 0x9A, 0x7B, 0xA0, 0xF4, 0xAA, 0xC5, 0x57, 0xB3, 0x16, 0xF9, 0xB5,
|
|
||||||
0x79, 0x20, 0xC1, 0x88, 0x9A, 0x00, 0x43, 0xB2, 0xC6, 0x84, 0x8D, 0x03, 0xF2, 0xD8, 0x90, 0x7A,
|
|
||||||
0x21, 0x37, 0x7E, 0xF7, 0x75, 0xE5, 0xFB, 0xC9, 0xDC, 0xAB, 0x4B, 0xBC, 0x35, 0x38, 0xB9, 0x3A,
|
|
||||||
0x53, 0x89, 0x7E, 0xD5, 0x94, 0x12, 0x2D, 0x9B, 0x91, 0x90, 0x1D, 0x4D, 0x0E, 0xE0, 0x93, 0xF3,
|
|
||||||
0xC1, 0xA1, 0x9B, 0x73, 0x27, 0x22, 0x41, 0x27, 0xEE, 0x2A, 0xD7, 0x45, 0xBC, 0x8F, 0x9B, 0xA2,
|
|
||||||
0x36, 0x11, 0x16, 0x37, 0x1A, 0xF1, 0x2E, 0x71, 0xCF, 0x86, 0x89, 0x83, 0x5A, 0xF1, 0x24, 0x6C,
|
|
||||||
0x56, 0x71, 0x53, 0xE4, 0xD2, 0xCB, 0xCA, 0x86, 0x1E, 0xA0, 0xD5, 0x83, 0x3B, 0xEF, 0x09, 0x09,
|
|
||||||
0xC2, 0x07, 0x53, 0x86, 0xE6, 0x8A, 0xC6, 0x70, 0xFB, 0x91, 0x43, 0xCB, 0x91, 0x6E, 0xA9, 0xBC,
|
|
||||||
0x31, 0x42, 0x61, 0x0C, 0x88, 0xB8, 0x2C, 0xED, 0xD8, 0xE6, 0xA3, 0xEC, 0xAC, 0xB9, 0x45, 0x5E,
|
|
||||||
0x2C, 0x73, 0x3F, 0x2E, 0x06, 0xE0, 0xBF, 0x73, 0xDD, 0x2E, 0x45, 0x50, 0x6C, 0x53, 0x55, 0xF0,
|
|
||||||
0x7F, 0x6E, 0x61, 0xFA, 0xA0, 0x7A, 0x1C, 0xF0, 0xBD, 0xAC, 0x48, 0x61, 0x03, 0x6B, 0xED, 0x54,
|
|
||||||
0x2A, 0x27, 0x94, 0xF6, 0xF9, 0x6A, 0x04, 0x08, 0x0B, 0x3C, 0xC3, 0x30, 0x66, 0x01, 0xFB, 0xDC,
|
|
||||||
0xC9, 0x65, 0x03, 0x83, 0x7D, 0x0A, 0xDF, 0xA5, 0x04, 0x14, 0xE4, 0xF2, 0x4C, 0x01, 0xDF, 0x04,
|
|
||||||
0xD2, 0x80, 0xB9, 0x9B, 0xD9, 0x5E, 0xF8, 0x2A, 0x93, 0x8D, 0x8C, 0x09, 0x9B, 0x38, 0xEC, 0x3B,
|
|
||||||
0xC4, 0x29, 0x90, 0x7C, 0x65, 0x3A, 0xF2, 0x4B, 0x69, 0xD3, 0x63, 0x9B, 0x40, 0x95, 0xC3, 0xFB,
|
|
||||||
0x67, 0x54, 0x40, 0x9B, 0x26, 0x9F, 0x52, 0xFE, 0xD8, 0xD0, 0x24, 0x9C, 0x5C, 0xD4, 0xEF, 0xDE,
|
|
||||||
0x28, 0x66, 0x75, 0x04, 0xCB, 0xA4, 0xC0, 0xB9, 0x4B, 0xC9, 0x20, 0x4B, 0x56, 0xC7, 0x86, 0xC5,
|
|
||||||
0x39, 0x45, 0x18, 0xA7, 0x48, 0x14, 0x1A, 0x51, 0xCA, 0xD0, 0xC0, 0x15, 0xDD, 0xC1, 0x28, 0x4A,
|
|
||||||
0x7A, 0xD2, 0x10, 0xEA, 0x83, 0xD3, 0x3A, 0xEF, 0x48, 0x29, 0x41, 0xA4, 0xD4, 0x57, 0xA6, 0x1D,
|
|
||||||
0x76, 0x24, 0x93, 0x58, 0x7E, 0xB7, 0xDD, 0x0B, 0xF2, 0xCE, 0x71, 0x55, 0xF5, 0xAB, 0x8C, 0xC8,
|
|
||||||
0x70, 0x59, 0x73, 0x69, 0x9D, 0x29, 0x5E, 0x59, 0xF4, 0xB2, 0xC4, 0x97, 0x75, 0xF0, 0x65, 0x1B,
|
|
||||||
0x66, 0x5F, 0xA4, 0x33, 0x5C, 0xC7, 0xBF, 0x45, 0xE6, 0x20, 0xC0, 0xBD, 0xAD, 0xAE, 0x9F, 0x97,
|
|
||||||
0x05, 0xD8, 0x04, 0x2B, 0x0A, 0x46, 0xE8, 0xB8, 0xCB, 0x00, 0xE2, 0x7C, 0x70, 0x1B, 0x49, 0xDE,
|
|
||||||
0x81, 0xEB, 0x24, 0xAC, 0x1B, 0x3E, 0x09, 0xFB, 0xAC, 0xB7, 0xF2, 0xD1, 0xB2, 0x78, 0xF3, 0xAC,
|
|
||||||
0xC7, 0x6A, 0xA2, 0x07, 0x4C, 0xED, 0x61, 0xAD, 0x04, 0x7F, 0x45, 0x83, 0x59, 0x31, 0x27, 0xF0,
|
|
||||||
0x16, 0x6B, 0x0C, 0xAA, 0xD4, 0xD1, 0xCB, 0x1C, 0x51, 0x41, 0x0D, 0x2F, 0x8F, 0xF9, 0xF9, 0x7F,
|
|
||||||
0x22, 0x89, 0x46, 0xF4, 0xB8, 0x93, 0x98, 0x9E, 0x3E, 0x23, 0xF1, 0x6E, 0x64, 0x08, 0xB6, 0xC9,
|
|
||||||
0x6E, 0x53, 0x53, 0xED, 0xAD, 0x21, 0xCD, 0x1A, 0xF0, 0x45, 0xFC, 0x14, 0x00, 0xEA, 0xF7, 0x42,
|
|
||||||
0xEE, 0xDA, 0x58, 0x0D, 0x85, 0xBC, 0x74, 0xFB, 0x73, 0x78, 0xB5, 0x5E, 0x5E, 0x6F, 0x6F, 0x7E,
|
|
||||||
0x39, 0xC2, 0x05, 0x50, 0xDB, 0x3D, 0xB8, 0xF3, 0x8F, 0x80, 0xEC, 0x46, 0x29, 0x39, 0x89, 0xF3,
|
|
||||||
0x55, 0x9C, 0x6A, 0x5F, 0x7C, 0xD9, 0x7C, 0x13, 0xE4, 0x56, 0x5E, 0xE9, 0x60, 0x19, 0xE2, 0x7D,
|
|
||||||
0xC4, 0x41, 0x92, 0x8D, 0xDA, 0x21, 0x58, 0x20, 0xE9, 0xA8, 0x4C, 0x16, 0x34, 0x99, 0xAC, 0xB7,
|
|
||||||
0x30, 0xBD, 0x39, 0x19, 0xAC, 0x9B, 0x4B, 0x27, 0xFA, 0x32, 0xC1, 0x48, 0xA1, 0x80, 0x34, 0x36,
|
|
||||||
0x1E, 0xFB, 0x92, 0x43, 0x35, 0x72, 0x2D, 0xEF, 0xD2, 0xF2, 0xFC, 0xC2, 0x85, 0xAB, 0x59, 0x40,
|
|
||||||
0x8D, 0x9D, 0x1A, 0x1F, 0xE2, 0x92, 0x87, 0xA2, 0xF9, 0x2C, 0x78, 0xE4, 0xC3, 0x26, 0x56, 0x07,
|
|
||||||
0xB3, 0x78, 0xAF, 0x79, 0x3D, 0x88, 0xF4, 0xAD, 0x66, 0x7C, 0x07, 0x58, 0x98, 0x82, 0x1A, 0x26,
|
|
||||||
0xF7, 0xFD, 0xCE, 0xFF, 0x75, 0xED, 0xAB, 0xBD, 0xAE, 0x6D, 0x5C, 0x28, 0x91, 0xF3, 0xB7, 0x5C,
|
|
||||||
0x27, 0x05, 0xEC, 0x3B, 0xE3, 0xDD, 0x93, 0x24, 0x7F, 0xAD, 0x14, 0xAA, 0x49, 0x61, 0x8F, 0x96,
|
|
||||||
0x1F, 0xAA, 0xB2, 0xEE, 0xA8, 0x24, 0x41, 0x7C, 0xDC, 0xF1, 0x28, 0x26, 0xE6, 0x7F, 0x98, 0x20,
|
|
||||||
0x50, 0x5F, 0x90, 0x21, 0x8A, 0x09, 0x26, 0x59, 0xD0, 0x07, 0x2F, 0xE1, 0x35, 0x4D, 0x0B, 0x20,
|
|
||||||
0xB2, 0xD5, 0xDD, 0xB5, 0xAC, 0x1B, 0xFE, 0xD9, 0xE3, 0x35, 0xF1, 0xB8, 0x3F, 0x3D, 0xFC, 0x0B,
|
|
||||||
0x5A, 0x57, 0xA9, 0x92, 0x2B, 0xC8, 0x3E, 0xC2, 0xAA, 0xEF, 0xB9, 0x98, 0x2C, 0xA8, 0xAB, 0xF6,
|
|
||||||
0xA1, 0xBF, 0xBC, 0x8D, 0x97, 0xA2, 0x74, 0xD9, 0xE5, 0x99, 0x85, 0x81, 0x15, 0xB0, 0xE7, 0x8B,
|
|
||||||
0x48, 0x86, 0xF4, 0x94, 0x9C, 0x62, 0x82, 0xD1, 0x2C, 0x24, 0x4B, 0xAC, 0x7A, 0xB8, 0x4E, 0x4A,
|
|
||||||
0xD2, 0xF6, 0xAA, 0xED, 0xE0, 0x9C, 0x98, 0xD2, 0xDF, 0xC1, 0xBC, 0xBF, 0x55, 0x7D, 0x40, 0xB5,
|
|
||||||
0xDE, 0xD4, 0x25, 0xBB, 0x81, 0xF4, 0x07, 0x1D, 0xE7, 0x3C, 0xB4, 0x62, 0xC9, 0x55, 0x0A, 0x3A,
|
|
||||||
0xD5, 0xCE, 0x97, 0xED, 0x30, 0x76, 0x76, 0x51, 0xBC, 0x8C, 0xE4, 0x54, 0xBE, 0xB7, 0xB5, 0xCD,
|
|
||||||
0xF8, 0x76, 0x37, 0x53, 0x2C, 0x9F, 0xE4, 0xC7, 0xEB, 0xF5, 0x8D, 0x23, 0x8A, 0xDA, 0xD1, 0xA9,
|
|
||||||
0xD8, 0x4C, 0x53, 0xF3, 0x49, 0xA7, 0x1A, 0x5D, 0xE5, 0x03, 0x49, 0x52, 0xD3, 0xE2, 0x1F, 0xA5,
|
|
||||||
0x35, 0x9C, 0xBB, 0x0B, 0xC7, 0x0D, 0xA4, 0x65, 0x54, 0x8B, 0x39, 0xF1, 0x3B, 0x67, 0x21, 0x71,
|
|
||||||
0x10, 0xE7, 0x76, 0xC4, 0xA8, 0xC2, 0x9D, 0x93, 0xC6, 0x51, 0xBA, 0x23
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "dsp/processor.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "correct.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
// Size of an encoded reed-solomon block.
|
|
||||||
inline const int RS_BLOCK_ENC_SIZE = 255;
|
|
||||||
|
|
||||||
// Size of a decoded reed-solomon block.
|
|
||||||
inline const int RS_BLOCK_DEC_SIZE = 223;
|
|
||||||
|
|
||||||
// Number of reed-solomon blocks.
|
|
||||||
inline const int RS_BLOCK_COUNT = 4;
|
|
||||||
|
|
||||||
// Scrambler sequence
|
|
||||||
extern const uint8_t RS_SCRAMBLER_SEQ[RS_BLOCK_ENC_SIZE*RS_BLOCK_COUNT];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RyFi Reed-Solomon Encoder.
|
|
||||||
*/
|
|
||||||
class RSEncoder : public dsp::Processor<uint8_t, uint8_t> {
|
|
||||||
using base_type = dsp::Processor<uint8_t, uint8_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a reed-solomon encoder specifying an input stream.
|
|
||||||
* @param in Input stream
|
|
||||||
*/
|
|
||||||
RSEncoder(dsp::stream<uint8_t>* in = NULL);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~RSEncoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode data.
|
|
||||||
* @param in Input bytes.
|
|
||||||
* @param out Output bytes.
|
|
||||||
* @param count Number of input bytes.
|
|
||||||
* @return Number of output bytes.
|
|
||||||
*/
|
|
||||||
int encode(const uint8_t* in, uint8_t* out, int count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
correct_reed_solomon* rs;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RyFi Reed-Solomon Decoder.
|
|
||||||
*/
|
|
||||||
class RSDecoder : public dsp::Processor<uint8_t, uint8_t> {
|
|
||||||
using base_type = dsp::Processor<uint8_t, uint8_t>;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a reed-solomon decoder specifying an input stream.
|
|
||||||
* @param in Input stream
|
|
||||||
*/
|
|
||||||
RSDecoder(dsp::stream<uint8_t>* in = NULL);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~RSDecoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode data.
|
|
||||||
* @param in Input bytes.
|
|
||||||
* @param out Output bytes.
|
|
||||||
* @param count Number of input bytes.
|
|
||||||
* @return Number of output bytes.
|
|
||||||
*/
|
|
||||||
int decode(uint8_t* in, uint8_t* out, int count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int run();
|
|
||||||
|
|
||||||
correct_reed_solomon* rs;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
#include "transmitter.h"
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
Transmitter::Transmitter(double baudrate, double samplerate) {
|
|
||||||
// Initialize the DSP
|
|
||||||
rs.setInput(&in);
|
|
||||||
conv.setInput(&rs.out);
|
|
||||||
framer.setInput(&conv.out);
|
|
||||||
resamp.init(&framer.out, baudrate, samplerate);
|
|
||||||
|
|
||||||
rrcTaps = dsp::taps::rootRaisedCosine<float>(511, 0.6, baudrate, samplerate);
|
|
||||||
// Normalize the taps
|
|
||||||
float tot = 0.0f;
|
|
||||||
for (int i = 0; i < rrcTaps.size; i++) {
|
|
||||||
tot += rrcTaps.taps[i];
|
|
||||||
}
|
|
||||||
for (int i = 0; i < rrcTaps.size; i++) {
|
|
||||||
rrcTaps.taps[i] /= tot;
|
|
||||||
}
|
|
||||||
|
|
||||||
rrc.init(&resamp.out, rrcTaps);
|
|
||||||
out = &rrc.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transmitter::~Transmitter() {
|
|
||||||
// Stop everything
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Transmitter::start() {
|
|
||||||
// Do nothing if already running
|
|
||||||
if (running) { return; }
|
|
||||||
|
|
||||||
// Start the worker thread
|
|
||||||
workerThread = std::thread(&Transmitter::worker, this);
|
|
||||||
|
|
||||||
// Start the DSP
|
|
||||||
rs.start();
|
|
||||||
conv.start();
|
|
||||||
framer.start();
|
|
||||||
resamp.start();
|
|
||||||
rrc.start();
|
|
||||||
|
|
||||||
// Update the running state
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Transmitter::stop() {
|
|
||||||
// Do nothing if not running
|
|
||||||
if (!running) { return; }
|
|
||||||
|
|
||||||
// Stop the worker thread
|
|
||||||
in.stopWriter();
|
|
||||||
if (workerThread.joinable()) { workerThread.join(); }
|
|
||||||
in.clearWriteStop();
|
|
||||||
|
|
||||||
// Stop the DSP
|
|
||||||
rs.stop();
|
|
||||||
conv.stop();
|
|
||||||
framer.stop();
|
|
||||||
resamp.stop();
|
|
||||||
rrc.stop();
|
|
||||||
|
|
||||||
// Update the running state
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Transmitter::send(const Packet& pkt) {
|
|
||||||
// Acquire the packet queue
|
|
||||||
std::lock_guard<std::mutex> lck(packetsMtx);
|
|
||||||
|
|
||||||
// If there are too many packets queued up, drop the packet
|
|
||||||
if (packets.size() >= MAX_QUEUE_SIZE) { return false; }
|
|
||||||
|
|
||||||
// Push the packet onto the queue
|
|
||||||
packets.push(pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Transmitter::txFrame(const Frame& frame) {
|
|
||||||
// Serialize the frame
|
|
||||||
int count = frame.serialize(in.writeBuf);
|
|
||||||
|
|
||||||
// Send it off
|
|
||||||
return in.swap(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet Transmitter::popPacket() {
|
|
||||||
// Acquire the packet queue
|
|
||||||
std::unique_lock<std::mutex> lck(packetsMtx);
|
|
||||||
|
|
||||||
// If no packets are available, return empty packet
|
|
||||||
if (!packets.size()) { return Packet(); }
|
|
||||||
|
|
||||||
// Pop the front packet and return it
|
|
||||||
Packet pkt = packets.front();
|
|
||||||
packets.pop();
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Transmitter::worker() {
|
|
||||||
Frame frame;
|
|
||||||
Packet pkt;
|
|
||||||
uint16_t counter = 0;
|
|
||||||
int pktToWrite = 0;
|
|
||||||
int pktWritten = 0;
|
|
||||||
uint8_t* pktBuffer = new uint8_t[Packet::MAX_SERIALIZED_SIZE];
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// Initialize the frame
|
|
||||||
frame.counter = counter++;
|
|
||||||
frame.firstPacket = PKT_OFFS_NONE;
|
|
||||||
frame.lastPacket = PKT_OFFS_NONE;
|
|
||||||
int frameOffset = 0;
|
|
||||||
|
|
||||||
// Fill the frame with as much packet data as possible
|
|
||||||
while (frameOffset < sizeof(Frame::content)) {
|
|
||||||
// If there is no packet in the process of being sent
|
|
||||||
if (!pktWritten) {
|
|
||||||
// If there is not enough space for the size of the packet
|
|
||||||
if ((sizeof(Frame::content) - frameOffset) < 2) {
|
|
||||||
// Fill the rest of the frame with noise and send it
|
|
||||||
for (int i = frameOffset; i < sizeof(Frame::content); i++) { frame.content[i] = rand(); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the next packet
|
|
||||||
pkt = popPacket();
|
|
||||||
|
|
||||||
// If there was an available packet
|
|
||||||
if (pkt) {
|
|
||||||
// Serialize the packet
|
|
||||||
pktToWrite = pkt.serializedSize();
|
|
||||||
pkt.serialize(pktBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If none was available
|
|
||||||
if (!pkt) {
|
|
||||||
// Fill the rest of the frame with noise and send it
|
|
||||||
for (int i = frameOffset; i < sizeof(Frame::content); i++) { frame.content[i] = rand(); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is the beginning of the packet
|
|
||||||
if (!pktWritten) {
|
|
||||||
//flog::debug("Starting to write a {} byte packet at offset {}", pktToWrite-2, frameOffset);
|
|
||||||
|
|
||||||
// If this is the first packet of the frame, update its offset
|
|
||||||
if (frame.firstPacket == PKT_OFFS_NONE) { frame.firstPacket = frameOffset; }
|
|
||||||
|
|
||||||
// Update the last packet pointer
|
|
||||||
frame.lastPacket = frameOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the amount of data writeable to the frame
|
|
||||||
int writeable = std::min<int>(pktToWrite - pktWritten, sizeof(Frame::content) - frameOffset);
|
|
||||||
|
|
||||||
// Copy the data to the frame
|
|
||||||
memcpy(&frame.content[frameOffset], &pktBuffer[pktWritten], writeable);
|
|
||||||
pktWritten += writeable;
|
|
||||||
frameOffset += writeable;
|
|
||||||
|
|
||||||
// If the packet is done being sent
|
|
||||||
if (pktWritten >= pktToWrite) {
|
|
||||||
// Prepare for a new packet
|
|
||||||
pktToWrite = 0;
|
|
||||||
pktWritten = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the frame
|
|
||||||
if (!txFrame(frame)) { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] pktBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "dsp/multirate/rational_resampler.h"
|
|
||||||
#include "dsp/taps/root_raised_cosine.h"
|
|
||||||
#include "dsp/filter/fir.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "frame.h"
|
|
||||||
#include "rs_codec.h"
|
|
||||||
#include "conv_codec.h"
|
|
||||||
#include "framing.h"
|
|
||||||
#include <queue>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace ryfi {
|
|
||||||
class Transmitter {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a transmitter.
|
|
||||||
* @param baudrate Baudrate to use over the air.
|
|
||||||
* @param samplerate Samplerate of the baseband.
|
|
||||||
*/
|
|
||||||
Transmitter(double baudrate, double samplerate);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Transmitter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the transmitter's DSP.
|
|
||||||
*/
|
|
||||||
void start();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the transmitter's DSP.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a packet.
|
|
||||||
* @param pkg Packet to send.
|
|
||||||
* @return True if the packet was send, false if it was dropped.
|
|
||||||
*/
|
|
||||||
bool send(const Packet& pkt);
|
|
||||||
|
|
||||||
// Baseband output
|
|
||||||
dsp::stream<dsp::complex_t>* out;
|
|
||||||
|
|
||||||
static inline const int MAX_QUEUE_SIZE = 32;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool txFrame(const Frame& frame);
|
|
||||||
Packet popPacket();
|
|
||||||
void worker();
|
|
||||||
|
|
||||||
// Packet queue
|
|
||||||
std::mutex packetsMtx;
|
|
||||||
std::queue<Packet> packets;
|
|
||||||
|
|
||||||
// DSP
|
|
||||||
dsp::stream<uint8_t> in;
|
|
||||||
RSEncoder rs;
|
|
||||||
ConvEncoder conv;
|
|
||||||
Framer framer;
|
|
||||||
dsp::multirate::RationalResampler<dsp::complex_t> resamp;
|
|
||||||
dsp::tap<float> rrcTaps;
|
|
||||||
dsp::filter::FIR<dsp::complex_t, float> rrc;
|
|
||||||
|
|
||||||
bool running = false;
|
|
||||||
std::thread workerThread;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
|
||||||
project(vor_receiver)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC "src/*.cpp")
|
|
||||||
|
|
||||||
include(${SDRPP_MODULE_CMAKE})
|
|
||||||
|
|
||||||
target_include_directories(vor_receiver PRIVATE "src/")
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#include <imgui.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <core.h>
|
|
||||||
#include <gui/style.h>
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <signal_path/signal_path.h>
|
|
||||||
#include <module.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <dsp/buffer/reshaper.h>
|
|
||||||
#include <dsp/sink/handler_sink.h>
|
|
||||||
#include <gui/widgets/constellation_diagram.h>
|
|
||||||
#include "vor_decoder.h"
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
|
||||||
|
|
||||||
SDRPP_MOD_INFO{
|
|
||||||
/* Name: */ "vor_receiver",
|
|
||||||
/* Description: */ "VOR Receiver for SDR++",
|
|
||||||
/* Author: */ "Ryzerth",
|
|
||||||
/* Version: */ 0, 1, 0,
|
|
||||||
/* Max instances */ -1
|
|
||||||
};
|
|
||||||
|
|
||||||
ConfigManager config;
|
|
||||||
|
|
||||||
#define INPUT_SAMPLE_RATE VOR_IN_SR
|
|
||||||
|
|
||||||
class VORReceiverModule : public ModuleManager::Instance {
|
|
||||||
public:
|
|
||||||
VORReceiverModule(std::string name) {
|
|
||||||
this->name = name;
|
|
||||||
|
|
||||||
// Load config
|
|
||||||
config.acquire();
|
|
||||||
// TODO: Load config
|
|
||||||
config.release();
|
|
||||||
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, true);
|
|
||||||
decoder = new vor::Decoder(vfo->output, 1);
|
|
||||||
decoder->onBearing.bind(&VORReceiverModule::onBearing, this);
|
|
||||||
|
|
||||||
decoder->start();
|
|
||||||
|
|
||||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~VORReceiverModule() {
|
|
||||||
decoder->stop();
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
gui::menu.removeEntry(name);
|
|
||||||
delete decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void postInit() {}
|
|
||||||
|
|
||||||
void enable() {
|
|
||||||
double bw = gui::waterfall.getBandwidth();
|
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, true);
|
|
||||||
|
|
||||||
decoder->setInput(vfo->output);
|
|
||||||
|
|
||||||
decoder->start();
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable() {
|
|
||||||
decoder->stop();
|
|
||||||
|
|
||||||
sigpath::vfoManager.deleteVFO(vfo);
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void menuHandler(void* ctx) {
|
|
||||||
VORReceiverModule* _this = (VORReceiverModule*)ctx;
|
|
||||||
|
|
||||||
float menuWidth = ImGui::GetContentRegionAvail().x;
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::beginDisabled(); }
|
|
||||||
|
|
||||||
ImGui::Text("Bearing: %f°", _this->bearing);
|
|
||||||
ImGui::Text("Quality: %0.1f%%", _this->quality);
|
|
||||||
|
|
||||||
if (!_this->enabled) { style::endDisabled(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void onBearing(float nbearing, float nquality) {
|
|
||||||
bearing = (180.0f * nbearing / FL_M_PI);
|
|
||||||
quality = nquality * 100.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool enabled = true;
|
|
||||||
|
|
||||||
// DSP Chain
|
|
||||||
VFOManager::VFO* vfo;
|
|
||||||
vor::Decoder* decoder;
|
|
||||||
|
|
||||||
float bearing = 0.0f, quality = 0.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
MOD_EXPORT void _INIT_() {
|
|
||||||
// Create default recording directory
|
|
||||||
std::string root = (std::string)core::args["root"];
|
|
||||||
json def = json({});
|
|
||||||
config.setPath(root + "/vor_receiver_config.json");
|
|
||||||
config.load(def);
|
|
||||||
config.enableAutoSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
|
|
||||||
return new VORReceiverModule(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
|
|
||||||
delete (VORReceiverModule*)instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOD_EXPORT void _END_() {
|
|
||||||
config.disableAutoSave();
|
|
||||||
config.save();
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#include "vor_decoder.h"
|
|
||||||
|
|
||||||
#define STDDEV_NORM_FACTOR 1.813799364234218f // 2.0f * FL_M_PI / sqrt(12)
|
|
||||||
|
|
||||||
namespace vor {
|
|
||||||
Decoder::Decoder(dsp::stream<dsp::complex_t>* in, double integrationTime) {
|
|
||||||
rx.init(in);
|
|
||||||
reshape.init(&rx.out, round(1000.0 * integrationTime), 0);
|
|
||||||
symSink.init(&reshape.out, dataHandler, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoder::~Decoder() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::setInput(dsp::stream<dsp::complex_t>* in) {
|
|
||||||
rx.setInput(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::start() {
|
|
||||||
rx.start();
|
|
||||||
reshape.start();
|
|
||||||
symSink.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::stop() {
|
|
||||||
rx.stop();
|
|
||||||
reshape.stop();
|
|
||||||
symSink.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::dataHandler(float* data, int count, void* ctx) {
|
|
||||||
// Get the instance from context
|
|
||||||
Decoder* _this = (Decoder*)ctx;
|
|
||||||
|
|
||||||
// Compute the mean and standard deviation of the
|
|
||||||
float mean, stddev;
|
|
||||||
volk_32f_stddev_and_mean_32f_x2(&stddev, &mean, data, count);
|
|
||||||
|
|
||||||
// Compute the signal quality
|
|
||||||
float quality = std::max<float>(1.0f - (stddev / STDDEV_NORM_FACTOR), 0.0f);
|
|
||||||
|
|
||||||
// Convert the phase difference to a compass heading
|
|
||||||
mean = -mean;
|
|
||||||
if (mean < 0) { mean = 2.0f*FL_M_PI + mean; }
|
|
||||||
|
|
||||||
// Call the handler
|
|
||||||
_this->onBearing(mean, quality);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#include "vor_receiver.h"
|
|
||||||
#include <dsp/buffer/reshaper.h>
|
|
||||||
#include <dsp/sink/handler_sink.h>
|
|
||||||
#include <utils/new_event.h>
|
|
||||||
|
|
||||||
namespace vor {
|
|
||||||
// Note: hard coded to 22KHz samplerate
|
|
||||||
class Decoder {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create an instance of a VOR decoder.
|
|
||||||
* @param in Input IQ stream at 22 KHz sampling rate.
|
|
||||||
* @param integrationTime Integration time of the bearing data in seconds.
|
|
||||||
*/
|
|
||||||
Decoder(dsp::stream<dsp::complex_t>* in, double integrationTime);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Decoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the input stream.
|
|
||||||
* @param in Input IQ stream at 22 KHz sampling rate.
|
|
||||||
*/
|
|
||||||
void setInput(dsp::stream<dsp::complex_t>* in);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the decoder.
|
|
||||||
*/
|
|
||||||
void start();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the decoder.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handler(bearing, signalQuality);
|
|
||||||
*/
|
|
||||||
NewEvent<float, float> onBearing;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void dataHandler(float* data, int count, void* ctx);
|
|
||||||
|
|
||||||
// DSP
|
|
||||||
Receiver rx;
|
|
||||||
dsp::buffer::Reshaper<float> reshape;
|
|
||||||
dsp::sink::Handler<float> symSink;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,106 +0,0 @@
|
|||||||
#include <dsp/sink.h>
|
|
||||||
#include <dsp/types.h>
|
|
||||||
#include <dsp/demod/am.h>
|
|
||||||
#include <dsp/demod/quadrature.h>
|
|
||||||
#include <dsp/convert/real_to_complex.h>
|
|
||||||
#include <dsp/channel/frequency_xlator.h>
|
|
||||||
#include <dsp/filter/fir.h>
|
|
||||||
#include <dsp/math/delay.h>
|
|
||||||
#include <dsp/math/conjugate.h>
|
|
||||||
#include <dsp/channel/rx_vfo.h>
|
|
||||||
#include "vor_fm_filter.h"
|
|
||||||
#include <utils/wav.h>
|
|
||||||
|
|
||||||
#define VOR_IN_SR 25e3
|
|
||||||
|
|
||||||
namespace vor {
|
|
||||||
class Receiver : public dsp::Processor<dsp::complex_t, float> {
|
|
||||||
using base_type = dsp::Processor<dsp::complex_t, float>;
|
|
||||||
public:
|
|
||||||
Receiver() {}
|
|
||||||
|
|
||||||
Receiver(dsp::stream<dsp::complex_t>* in) { init(in); }
|
|
||||||
|
|
||||||
~Receiver() {
|
|
||||||
if (!base_type::_block_init) { return; }
|
|
||||||
base_type::stop();
|
|
||||||
dsp::taps::free(fmfTaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(dsp::stream<dsp::complex_t>* in) {
|
|
||||||
amd.init(NULL, dsp::demod::AM<float>::CARRIER, VOR_IN_SR, 50.0f / VOR_IN_SR, 5.0f / VOR_IN_SR, 100.0f / VOR_IN_SR, VOR_IN_SR);
|
|
||||||
amr2c.init(NULL);
|
|
||||||
fmr2c.init(NULL);
|
|
||||||
fmx.init(NULL, -9960, VOR_IN_SR);
|
|
||||||
fmfTaps = dsp::taps::fromArray(FM_TAPS_COUNT, fm_taps);
|
|
||||||
fmf.init(NULL, fmfTaps);
|
|
||||||
fmd.init(NULL, 600, VOR_IN_SR);
|
|
||||||
amde.init(NULL, FM_TAPS_COUNT / 2);
|
|
||||||
amv.init(NULL, VOR_IN_SR, 1000, 30, 30);
|
|
||||||
fmv.init(NULL, VOR_IN_SR, 1000, 30, 30);
|
|
||||||
|
|
||||||
base_type::init(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
int process(dsp::complex_t* in, float* out, int count) {
|
|
||||||
// Demodulate the AM outer modulation
|
|
||||||
volk_32fc_magnitude_32f(amd.out.writeBuf, (lv_32fc_t*)in, count);
|
|
||||||
amr2c.process(count, amd.out.writeBuf, amr2c.out.writeBuf);
|
|
||||||
|
|
||||||
// Isolate the FM subcarrier
|
|
||||||
fmx.process(count, amr2c.out.writeBuf, fmx.out.writeBuf);
|
|
||||||
fmf.process(count, fmx.out.writeBuf, fmx.out.writeBuf);
|
|
||||||
|
|
||||||
// Demodulate the FM subcarrier
|
|
||||||
fmd.process(count, fmx.out.writeBuf, fmd.out.writeBuf);
|
|
||||||
fmr2c.process(count, fmd.out.writeBuf, fmr2c.out.writeBuf);
|
|
||||||
|
|
||||||
// Delay the AM signal by the same amount as the FM one
|
|
||||||
amde.process(count, amr2c.out.writeBuf, amr2c.out.writeBuf);
|
|
||||||
|
|
||||||
// Isolate the 30Hz component on both the AM and FM channels
|
|
||||||
int rcount = amv.process(count, amr2c.out.writeBuf, amv.out.writeBuf);
|
|
||||||
fmv.process(count, fmr2c.out.writeBuf, fmv.out.writeBuf);
|
|
||||||
|
|
||||||
// If no data was returned, we're done for this round
|
|
||||||
if (!rcount) { return 0; }
|
|
||||||
|
|
||||||
// Conjugate FM reference
|
|
||||||
volk_32fc_conjugate_32fc((lv_32fc_t*)fmv.out.writeBuf, (lv_32fc_t*)fmv.out.writeBuf, rcount);
|
|
||||||
|
|
||||||
// Multiply both together
|
|
||||||
volk_32fc_x2_multiply_32fc((lv_32fc_t*)amv.out.writeBuf, (lv_32fc_t*)amv.out.writeBuf, (lv_32fc_t*)fmv.out.writeBuf, rcount);
|
|
||||||
|
|
||||||
// Compute angle
|
|
||||||
volk_32fc_s32f_atan2_32f(out, (lv_32fc_t*)amv.out.writeBuf, 1.0f, rcount);
|
|
||||||
|
|
||||||
return rcount;
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
int count = base_type::_in->read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
|
|
||||||
int outCount = process(base_type::_in->readBuf, base_type::out.writeBuf, count);
|
|
||||||
|
|
||||||
// Swap if some data was generated
|
|
||||||
base_type::_in->flush();
|
|
||||||
if (outCount) {
|
|
||||||
if (!base_type::out.swap(outCount)) { return -1; }
|
|
||||||
}
|
|
||||||
return outCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
dsp::demod::AM<float> amd;
|
|
||||||
dsp::convert::RealToComplex amr2c;
|
|
||||||
dsp::convert::RealToComplex fmr2c;
|
|
||||||
dsp::channel::FrequencyXlator fmx;
|
|
||||||
dsp::tap<float> fmfTaps;
|
|
||||||
dsp::filter::FIR<dsp::complex_t, float> fmf;
|
|
||||||
dsp::demod::Quadrature fmd;
|
|
||||||
dsp::math::Delay<dsp::complex_t> amde;
|
|
||||||
dsp::channel::RxVFO amv;
|
|
||||||
dsp::channel::RxVFO fmv;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,52 +25,10 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,52 +25,10 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM debian:trixie
|
FROM debian:buster
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
COPY do_build.sh /root
|
COPY do_build.sh /root
|
||||||
RUN chmod +x /root/do_build.sh
|
RUN chmod +x /root/do_build.sh
|
||||||
35
docker_builds/debian_buster/do_build.sh
Normal file
35
docker_builds/debian_buster/do_build.sh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
cd /root
|
||||||
|
|
||||||
|
# Install dependencies and tools
|
||||||
|
apt update
|
||||||
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
|
# Install SDRPlay libraries
|
||||||
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
|
# Install libperseus
|
||||||
|
git clone https://github.com/Microtelecom/libperseus-sdr
|
||||||
|
cd libperseus-sdr
|
||||||
|
autoreconf -i
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
ldconfig
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd SDRPlusPlus
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk1-dev, librtaudio-dev, libzstd-dev'
|
||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,52 +25,10 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
cd /root
|
|
||||||
|
|
||||||
# Install dependencies and tools
|
|
||||||
apt update
|
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
|
||||||
|
|
||||||
# Install libperseus
|
|
||||||
git clone https://github.com/Microtelecom/libperseus-sdr
|
|
||||||
cd libperseus-sdr
|
|
||||||
autoreconf -i
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
ldconfig
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
|
||||||
make VERBOSE=1 -j2
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk-dev, librtaudio-dev, libzstd-dev'
|
|
||||||
@@ -12,14 +12,13 @@ apt update
|
|||||||
# Install dependencies and tools
|
# Install dependencies and tools
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev libudev-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev libudev-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install a more recent libusb version
|
# Install a more recent libusb version
|
||||||
@@ -52,26 +51,6 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Fix missing .pc file for codec2
|
# Fix missing .pc file for codec2
|
||||||
echo 'prefix=/usr/' >> /usr/share/pkgconfig/codec2.pc
|
echo 'prefix=/usr/' >> /usr/share/pkgconfig/codec2.pc
|
||||||
echo 'libdir=/usr/include/x86_64-linux-gnu/' >> /usr/share/pkgconfig/codec2.pc
|
echo 'libdir=/usr/include/x86_64-linux-gnu/' >> /usr/share/pkgconfig/codec2.pc
|
||||||
@@ -83,35 +62,13 @@ echo 'Version: 0.7' >> /usr/share/pkgconfig/codec2.pc
|
|||||||
echo 'Libs: -L/usr/include/x86_64-linux-gnu/ -lcodec2' >> /usr/share/pkgconfig/codec2.pc
|
echo 'Libs: -L/usr/include/x86_64-linux-gnu/ -lcodec2' >> /usr/share/pkgconfig/codec2.pc
|
||||||
echo 'Cflags: -I/usr/include/codec2' >> /usr/share/pkgconfig/codec2.pc
|
echo 'Cflags: -I/usr/include/codec2' >> /usr/share/pkgconfig/codec2.pc
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Build SDR++ Itself
|
# Build SDR++ Itself
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
# Generate package
|
# Generate package
|
||||||
cd ..
|
cd ..
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk1-dev, librtaudio-dev, libzstd-dev'
|
sh make_debian_package.sh ./build 'libfftw3-bin, libglfw3, libvolk1-bin, librtaudio6, libzstd1'
|
||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,53 +25,11 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev, libzstd-dev'
|
sh make_debian_package.sh ./build 'libfftw3-bin, libglfw3, libvolk2-bin, librtaudio6, libzstd1'
|
||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,53 +25,11 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev, libzstd-dev'
|
sh make_debian_package.sh ./build 'libfftw3-bin, libglfw3, libvolk2-bin, librtaudio6, libzstd1'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:oracular
|
FROM ubuntu:mantic
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
COPY do_build.sh /root
|
COPY do_build.sh /root
|
||||||
RUN chmod +x /root/do_build.sh
|
RUN chmod +x /root/do_build.sh
|
||||||
35
docker_builds/ubuntu_mantic/do_build.sh
Normal file
35
docker_builds/ubuntu_mantic/do_build.sh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
cd /root
|
||||||
|
|
||||||
|
# Install dependencies and tools
|
||||||
|
apt update
|
||||||
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
|
# Install SDRPlay libraries
|
||||||
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
|
# Install libperseus
|
||||||
|
git clone https://github.com/Microtelecom/libperseus-sdr
|
||||||
|
cd libperseus-sdr
|
||||||
|
autoreconf -i
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
ldconfig
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd SDRPlusPlus
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
sh make_debian_package.sh ./build 'libfftw3-bin, libglfw3, libvolk-bin, librtaudio6, libzstd1'
|
||||||
@@ -6,14 +6,13 @@ cd /root
|
|||||||
apt update
|
apt update
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
libcodec2-dev autoconf libtool xxd
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
# Install SDRPlay libraries
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1.run
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
7z x ./SDRplay_RSP_API-Linux-3.15.1
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
cp x86_64/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
cp inc/* /usr/include/
|
||||||
|
|
||||||
# Install libperseus
|
# Install libperseus
|
||||||
@@ -26,53 +25,11 @@ make install
|
|||||||
ldconfig
|
ldconfig
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
cd SDRPlusPlus
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||||
make VERBOSE=1 -j2
|
make VERBOSE=1 -j2
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk-dev, librtaudio-dev, libzstd-dev'
|
sh make_debian_package.sh ./build 'libfftw3-bin, libglfw3, libvolk-bin, librtaudio6, libzstd1'
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
cd /root
|
|
||||||
|
|
||||||
# Install dependencies and tools
|
|
||||||
apt update
|
|
||||||
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
|
|
||||||
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
|
|
||||||
libcodec2-dev autoconf libtool xxd libspdlog-dev
|
|
||||||
|
|
||||||
# Install SDRPlay libraries
|
|
||||||
SDRPLAY_ARCH=$(dpkg --print-architecture)
|
|
||||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.15.2.run
|
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2.run
|
|
||||||
7z x ./SDRplay_RSP_API-Linux-3.15.2
|
|
||||||
cp $SDRPLAY_ARCH/libsdrplay_api.so.3.15 /usr/lib/libsdrplay_api.so
|
|
||||||
cp inc/* /usr/include/
|
|
||||||
|
|
||||||
# Install libperseus
|
|
||||||
git clone https://github.com/Microtelecom/libperseus-sdr
|
|
||||||
cd libperseus-sdr
|
|
||||||
autoreconf -i
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
ldconfig
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Install librfnm
|
|
||||||
git clone https://github.com/AlexandreRouma/librfnm
|
|
||||||
cd librfnm
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libfobos
|
|
||||||
git clone https://github.com/AlexandreRouma/libfobos
|
|
||||||
cd libfobos
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libhydrasdr
|
|
||||||
git clone https://github.com/hydrasdr/rfone_host
|
|
||||||
cd rfone_host
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
# Install libdlcr
|
|
||||||
wget https://dragnlabs.com/host-tools/dlcr_host_v0.3.0.zip
|
|
||||||
mkdir dlcr_host
|
|
||||||
cd dlcr_host
|
|
||||||
7z x ../dlcr_host_v0.3.0.zip
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
cd SDRPlusPlus
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DOPT_BUILD_HYDRASDR_SOURCE=ON -DOPT_BUILD_DRAGONLABS_SOURCE=ON
|
|
||||||
make VERBOSE=1 -j2
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk-dev, librtaudio-dev, libzstd-dev'
|
|
||||||
@@ -28,8 +28,6 @@ bundle_is_not_to_be_installed() {
|
|||||||
if [ "$1" = "Security" ]; then echo 1; fi
|
if [ "$1" = "Security" ]; then echo 1; fi
|
||||||
if [ "$1" = "AppleFSCompression" ]; then echo 1; fi
|
if [ "$1" = "AppleFSCompression" ]; then echo 1; fi
|
||||||
if [ "$1" = "libsdrplay_api.so.3.14" ]; then echo 1; fi
|
if [ "$1" = "libsdrplay_api.so.3.14" ]; then echo 1; fi
|
||||||
if [ "$1" = "libsdrplay_api.so.3.15" ]; then echo 1; fi
|
|
||||||
if [ "$1" = "libxml2.2.dylib" ]; then echo 1; fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ========================= FOR INTERNAL USE ONLY =========================
|
# ========================= FOR INTERNAL USE ONLY =========================
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ mkdir sdrpp_debian_amd64/DEBIAN
|
|||||||
# Create package info
|
# Create package info
|
||||||
echo Create package info
|
echo Create package info
|
||||||
echo Package: sdrpp >> sdrpp_debian_amd64/DEBIAN/control
|
echo Package: sdrpp >> sdrpp_debian_amd64/DEBIAN/control
|
||||||
echo Version: 1.2.1$BUILD_NO >> sdrpp_debian_amd64/DEBIAN/control
|
echo Version: 1.2.0$BUILD_NO >> sdrpp_debian_amd64/DEBIAN/control
|
||||||
echo Maintainer: Ryzerth >> sdrpp_debian_amd64/DEBIAN/control
|
echo Maintainer: Ryzerth >> sdrpp_debian_amd64/DEBIAN/control
|
||||||
echo Architecture: all >> sdrpp_debian_amd64/DEBIAN/control
|
echo Architecture: all >> sdrpp_debian_amd64/DEBIAN/control
|
||||||
echo Description: Bloat-free SDR receiver software >> sdrpp_debian_amd64/DEBIAN/control
|
echo Description: Bloat-free SDR receiver software >> sdrpp_debian_amd64/DEBIAN/control
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ cp -R root/res/* $BUNDLE/Contents/Resources/
|
|||||||
bundle_create_icns root/res/icons/sdrpp.macos.png $BUNDLE/Contents/Resources/sdrpp
|
bundle_create_icns root/res/icons/sdrpp.macos.png $BUNDLE/Contents/Resources/sdrpp
|
||||||
|
|
||||||
# Create the property list
|
# Create the property list
|
||||||
bundle_create_plist sdrpp SDR++ org.sdrpp.sdrpp 1.2.1 sdrp sdrpp sdrpp $BUNDLE/Contents/Info.plist
|
bundle_create_plist sdrpp SDR++ org.sdrpp.sdrpp 1.2.0 sdrp sdrpp sdrpp $BUNDLE/Contents/Info.plist
|
||||||
|
|
||||||
# ========================= Install binaries =========================
|
# ========================= Install binaries =========================
|
||||||
|
|
||||||
@@ -34,17 +34,12 @@ bundle_install_binary $BUNDLE $BUNDLE/Contents/Frameworks $BUILD_DIR/core/libsdr
|
|||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/airspy_source/airspy_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/airspy_source/airspy_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/airspyhf_source/airspyhf_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/airspyhf_source/airspyhf_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/bladerf_source/bladerf_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/bladerf_source/bladerf_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/dragonlabs_source/dragonlabs_source.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/file_source/file_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/file_source/file_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/fobossdr_source/fobossdr_source.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hackrf_source/hackrf_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hackrf_source/hackrf_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hermes_source/hermes_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hermes_source/hermes_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hydrasdr_source/hydrasdr_source.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/limesdr_source/limesdr_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/limesdr_source/limesdr_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/network_source/network_source.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/perseus_source/perseus_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/perseus_source/perseus_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/plutosdr_source/plutosdr_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/plutosdr_source/plutosdr_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rfnm_source/rfnm_source.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rfspace_source/rfspace_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rfspace_source/rfspace_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_sdr_source/rtl_sdr_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_sdr_source/rtl_sdr_source.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_tcp_source/rtl_tcp_source.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_tcp_source/rtl_tcp_source.dylib
|
||||||
@@ -59,7 +54,6 @@ bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/sink_modules/n
|
|||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/sink_modules/new_portaudio_sink/new_portaudio_sink.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/sink_modules/new_portaudio_sink/new_portaudio_sink.dylib
|
||||||
|
|
||||||
# Decoder modules
|
# Decoder modules
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/atv_decoder/atv_decoder.dylib
|
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/m17_decoder/m17_decoder.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/m17_decoder/m17_decoder.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/meteor_demodulator/meteor_demodulator.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/meteor_demodulator/meteor_demodulator.dylib
|
||||||
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/radio/radio.dylib
|
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_modules/radio/radio.dylib
|
||||||
|
|||||||
@@ -7,100 +7,86 @@ mkdir sdrpp_windows_x64
|
|||||||
cp -Recurse $root_dir/* sdrpp_windows_x64/
|
cp -Recurse $root_dir/* sdrpp_windows_x64/
|
||||||
|
|
||||||
# Copy core
|
# Copy core
|
||||||
cp $build_dir/Release/* sdrpp_windows_x64/
|
cp $build_dir/Debug/* sdrpp_windows_x64/
|
||||||
|
cp $build_dir/core/Debug/sdrpp_core.pdb sdrpp_windows_x64/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/volk.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/volk.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
# Copy source modules
|
# Copy source modules
|
||||||
cp $build_dir/source_modules/airspy_source/Release/airspy_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/airspy_source/Debug/airspy_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/airspy.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/airspy.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/airspyhf_source/Release/airspyhf_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/airspyhf_source/Debug/airspyhf_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/airspyhf.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/airspyhf.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/audio_source/Release/audio_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/audio_source/Debug/audio_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/bladerf_source/Release/bladerf_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/bladerf_source/Debug/bladerf_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/bladeRF.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/bladeRF.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/file_source/Release/file_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/file_source/Debug/file_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/fobossdr_source/Release/fobossdr_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/hackrf_source/Debug/hackrf_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/RigExpert/Fobos/bin/fobos.dll' sdrpp_windows_x64/
|
|
||||||
|
|
||||||
cp $build_dir/source_modules/hackrf_source/Release/hackrf_source.dll sdrpp_windows_x64/modules/
|
|
||||||
cp 'C:/Program Files/PothosSDR/bin/hackrf.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/hackrf.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/hermes_source/Release/hermes_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/hermes_source/Debug/hermes_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/hydrasdr_source/Release/hydrasdr_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/limesdr_source/Debug/limesdr_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/hydrasdr-host/bin/hydrasdr.dll' sdrpp_windows_x64/
|
|
||||||
|
|
||||||
cp $build_dir/source_modules/limesdr_source/Release/limesdr_source.dll sdrpp_windows_x64/modules/
|
|
||||||
cp 'C:/Program Files/PothosSDR/bin/LimeSuite.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/LimeSuite.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/network_source/Release/network_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/perseus_source/Debug/perseus_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/perseus_source/Release/perseus_source.dll sdrpp_windows_x64/modules/
|
|
||||||
cp 'C:/Program Files/PothosSDR/bin/perseus-sdr.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/perseus-sdr.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/plutosdr_source/Release/plutosdr_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/plutosdr_source/Debug/plutosdr_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/libiio.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/libiio.dll' sdrpp_windows_x64/
|
||||||
cp 'C:/Program Files/PothosSDR/bin/libad9361.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/libad9361.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/rfnm_source/Release/rfnm_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/rfspace_source/Debug/rfspace_source.dll sdrpp_windows_x64/modules/
|
||||||
cp 'C:/Program Files/RFNM/bin/rfnm.dll' sdrpp_windows_x64/
|
|
||||||
cp 'C:/Program Files/RFNM/bin/spdlog.dll' sdrpp_windows_x64/
|
|
||||||
cp 'C:/Program Files/RFNM/bin/fmt.dll' sdrpp_windows_x64/
|
|
||||||
|
|
||||||
cp $build_dir/source_modules/rfspace_source/Release/rfspace_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/rtl_sdr_source/Debug/rtl_sdr_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/rtl_sdr_source/Release/rtl_sdr_source.dll sdrpp_windows_x64/modules/
|
|
||||||
cp 'C:/Program Files/PothosSDR/bin/rtlsdr.dll' sdrpp_windows_x64/
|
cp 'C:/Program Files/PothosSDR/bin/rtlsdr.dll' sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/source_modules/rtl_tcp_source/Release/rtl_tcp_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/rtl_tcp_source/Debug/rtl_tcp_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/sdrplay_source/Release/sdrplay_source.dll sdrpp_windows_x64/modules/ -ErrorAction SilentlyContinue
|
cp $build_dir/source_modules/sdrplay_source/Debug/sdrplay_source.dll sdrpp_windows_x64/modules/ -ErrorAction SilentlyContinue
|
||||||
cp 'C:/Program Files/SDRplay/API/x64/sdrplay_api.dll' sdrpp_windows_x64/ -ErrorAction SilentlyContinue
|
cp 'C:/Program Files/SDRplay/API/x64/sdrplay_api.dll' sdrpp_windows_x64/ -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
cp $build_dir/source_modules/sdrpp_server_source/Release/sdrpp_server_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/sdrpp_server_source/Debug/sdrpp_server_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/source_modules/spyserver_source/Release/spyserver_source.dll sdrpp_windows_x64/modules/
|
cp $build_dir/source_modules/spyserver_source/Debug/spyserver_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
# cp $build_dir/source_modules/usrp_source/Release/usrp_source.dll sdrpp_windows_x64/modules/
|
# cp $build_dir/source_modules/usrp_source/Debug/usrp_source.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
|
|
||||||
# Copy sink modules
|
# Copy sink modules
|
||||||
cp $build_dir/sink_modules/audio_sink/Release/audio_sink.dll sdrpp_windows_x64/modules/
|
cp $build_dir/sink_modules/audio_sink/Debug/audio_sink.dll sdrpp_windows_x64/modules/
|
||||||
cp "C:/Program Files (x86)/RtAudio/bin/rtaudio.dll" sdrpp_windows_x64/
|
cp "C:/Program Files (x86)/RtAudio/bin/rtaudio.dll" sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/sink_modules/network_sink/Release/network_sink.dll sdrpp_windows_x64/modules/
|
cp $build_dir/sink_modules/network_sink/Debug/network_sink.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
|
|
||||||
# Copy decoder modules
|
# Copy decoder modules
|
||||||
cp $build_dir/decoder_modules/atv_decoder/Release/atv_decoder.dll sdrpp_windows_x64/modules/
|
cp $build_dir/decoder_modules/m17_decoder/Debug/m17_decoder.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/decoder_modules/m17_decoder/Release/m17_decoder.dll sdrpp_windows_x64/modules/
|
|
||||||
cp "C:/Program Files/codec2/lib/libcodec2.dll" sdrpp_windows_x64/
|
cp "C:/Program Files/codec2/lib/libcodec2.dll" sdrpp_windows_x64/
|
||||||
|
|
||||||
cp $build_dir/decoder_modules/meteor_demodulator/Release/meteor_demodulator.dll sdrpp_windows_x64/modules/
|
cp $build_dir/decoder_modules/meteor_demodulator/Debug/meteor_demodulator.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/decoder_modules/radio/Release/radio.dll sdrpp_windows_x64/modules/
|
cp $build_dir/decoder_modules/radio/Debug/radio.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
|
|
||||||
# Copy misc modules
|
# Copy misc modules
|
||||||
cp $build_dir/misc_modules/discord_integration/Release/discord_integration.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/discord_integration/Debug/discord_integration.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/frequency_manager/Release/frequency_manager.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/frequency_manager/Debug/frequency_manager.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/iq_exporter/Release/iq_exporter.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/iq_exporter/Debug/iq_exporter.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/recorder/Release/recorder.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/recorder/Debug/recorder.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/rigctl_client/Release/rigctl_client.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/rigctl_client/Debug/rigctl_client.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/rigctl_server/Release/rigctl_server.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/rigctl_server/Debug/rigctl_server.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
cp $build_dir/misc_modules/scanner/Release/scanner.dll sdrpp_windows_x64/modules/
|
cp $build_dir/misc_modules/scanner/Debug/scanner.dll sdrpp_windows_x64/modules/
|
||||||
|
|
||||||
|
|
||||||
# Copy supporting libs
|
# Copy supporting libs
|
||||||
|
|||||||
12
min_broken/main.cpp
Normal file
12
min_broken/main.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
std::recursive_mutex mtx;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
||||||
|
|
||||||
|
printf("Works just fine!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required (VERSION 3.13.0)
|
cmake_minimum_required (VERSION 3.2.0)
|
||||||
project (DiscordRPC)
|
project (DiscordRPC)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|||||||
@@ -168,9 +168,10 @@ public:
|
|||||||
writer.setSamplerate(samplerate);
|
writer.setSamplerate(samplerate);
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
|
std::string type = (recMode == RECORDER_MODE_AUDIO) ? "audio" : "baseband";
|
||||||
std::string vfoName = (recMode == RECORDER_MODE_AUDIO) ? selectedStreamName : "";
|
std::string vfoName = (recMode == RECORDER_MODE_AUDIO) ? selectedStreamName : "";
|
||||||
std::string extension = ".wav";
|
std::string extension = ".wav";
|
||||||
std::string expandedPath = expandString(folderSelect.path + "/" + genFileName(nameTemplate, recMode, vfoName) + extension);
|
std::string expandedPath = expandString(folderSelect.path + "/" + genFileName(nameTemplate, type, vfoName) + extension);
|
||||||
if (!writer.open(expandedPath)) {
|
if (!writer.open(expandedPath)) {
|
||||||
flog::error("Failed to open file for recording: {0}", expandedPath);
|
flog::error("Failed to open file for recording: {0}", expandedPath);
|
||||||
return;
|
return;
|
||||||
@@ -248,6 +249,7 @@ private:
|
|||||||
}
|
}
|
||||||
ImGui::Columns(1, CONCAT("EndRecorderModeColumns##_", _this->name), false);
|
ImGui::Columns(1, CONCAT("EndRecorderModeColumns##_", _this->name), false);
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
if (_this->recording) { style::endDisabled(); }
|
||||||
|
|
||||||
// Recording path
|
// Recording path
|
||||||
if (_this->folderSelect.render("##_recorder_fold_" + _this->name)) {
|
if (_this->folderSelect.render("##_recorder_fold_" + _this->name)) {
|
||||||
@@ -282,11 +284,8 @@ private:
|
|||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_this->recording) { style::endDisabled(); }
|
|
||||||
|
|
||||||
// Show additional audio options
|
// Show additional audio options
|
||||||
if (_this->recMode == RECORDER_MODE_AUDIO) {
|
if (_this->recMode == RECORDER_MODE_AUDIO) {
|
||||||
if (_this->recording) { style::beginDisabled(); }
|
|
||||||
ImGui::LeftLabel("Stream");
|
ImGui::LeftLabel("Stream");
|
||||||
ImGui::FillWidth();
|
ImGui::FillWidth();
|
||||||
if (ImGui::Combo(CONCAT("##_recorder_stream_", _this->name), &_this->streamId, _this->audioStreams.txt)) {
|
if (ImGui::Combo(CONCAT("##_recorder_stream_", _this->name), &_this->streamId, _this->audioStreams.txt)) {
|
||||||
@@ -295,7 +294,6 @@ private:
|
|||||||
config.conf[_this->name]["audioStream"] = _this->audioStreams.key(_this->streamId);
|
config.conf[_this->name]["audioStream"] = _this->audioStreams.key(_this->streamId);
|
||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
if (_this->recording) { style::endDisabled(); }
|
|
||||||
|
|
||||||
_this->updateAudioMeter(_this->audioLvl);
|
_this->updateAudioMeter(_this->audioLvl);
|
||||||
ImGui::FillWidth();
|
ImGui::FillWidth();
|
||||||
@@ -451,7 +449,7 @@ private:
|
|||||||
{ RADIO_IFACE_MODE_RAW, "RAW" }
|
{ RADIO_IFACE_MODE_RAW, "RAW" }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string genFileName(std::string templ, int mode, std::string name) {
|
std::string genFileName(std::string templ, std::string type, std::string name) {
|
||||||
// Get data
|
// Get data
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
tm* ltm = localtime(&now);
|
tm* ltm = localtime(&now);
|
||||||
@@ -461,9 +459,6 @@ private:
|
|||||||
freq += gui::waterfall.vfos[name]->generalOffset;
|
freq += gui::waterfall.vfos[name]->generalOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the recording type string
|
|
||||||
std::string type = (recMode == RECORDER_MODE_AUDIO) ? "audio" : "baseband";
|
|
||||||
|
|
||||||
// Format to string
|
// Format to string
|
||||||
char freqStr[128];
|
char freqStr[128];
|
||||||
char hourStr[128];
|
char hourStr[128];
|
||||||
@@ -472,7 +467,7 @@ private:
|
|||||||
char dayStr[128];
|
char dayStr[128];
|
||||||
char monStr[128];
|
char monStr[128];
|
||||||
char yearStr[128];
|
char yearStr[128];
|
||||||
const char* modeStr = (recMode == RECORDER_MODE_AUDIO) ? "Unknown" : "IQ";
|
const char* modeStr = "Unknown";
|
||||||
sprintf(freqStr, "%.0lfHz", freq);
|
sprintf(freqStr, "%.0lfHz", freq);
|
||||||
sprintf(hourStr, "%02d", ltm->tm_hour);
|
sprintf(hourStr, "%02d", ltm->tm_hour);
|
||||||
sprintf(minStr, "%02d", ltm->tm_min);
|
sprintf(minStr, "%02d", ltm->tm_min);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
SDRPP_MOD_INFO{
|
SDRPP_MOD_INFO{
|
||||||
/* Name: */ "scanner",
|
/* Name: */ "scanner",
|
||||||
|
|||||||
33
readme.md
33
readme.md
@@ -41,13 +41,14 @@ To create a desktop shortcut, rightclick the exe and select `Send to -> Desktop
|
|||||||
|
|
||||||
Download the latest release from [the Releases page](https://github.com/AlexandreRouma/SDRPlusPlus/releases) and extract to the directory of your choice.
|
Download the latest release from [the Releases page](https://github.com/AlexandreRouma/SDRPlusPlus/releases) and extract to the directory of your choice.
|
||||||
|
|
||||||
Then, use apt to install it:
|
Then, run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt install path/to/the/sdrpp_debian_amd64.deb
|
sudo apt install libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libiio-dev libad9361-dev librtaudio-dev libhackrf-dev
|
||||||
|
sudo dpkg -i sdrpp_debian_amd64.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
**IMPORTANT: You must install the drivers for your SDR. Follow instructions from your manufacturer as to how to do this on your particular distro.**
|
If `libvolk2-dev` is not available, use `libvolk1-dev`.
|
||||||
|
|
||||||
### Arch-based
|
### Arch-based
|
||||||
|
|
||||||
@@ -324,16 +325,13 @@ Modules in beta are still included in releases for the most part but not enabled
|
|||||||
| audio_source | Working | rtaudio | OPT_BUILD_AUDIO_SOURCE | ✅ | ✅ | ✅ |
|
| audio_source | Working | rtaudio | OPT_BUILD_AUDIO_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ✅ (not Debian Buster) | ✅ |
|
| bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ✅ (not Debian Buster) | ✅ |
|
||||||
| file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ |
|
| file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| fobossdr_source | Working | libfobos | OPT_BUILD_FOBOSSDR_SOURCE | ✅ | ✅ | ✅ |
|
|
||||||
| hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ |
|
| hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| harogic_source | Beta | htra_api | OPT_BUILD_HAROGIC_SOURCE | ⛔ | ⛔ | ✅ |
|
|
||||||
| hermes_source | Beta | - | OPT_BUILD_HERMES_SOURCE | ✅ | ✅ | ✅ |
|
| hermes_source | Beta | - | OPT_BUILD_HERMES_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| kcsdr_source | Unfinished | libkcsdr | OPT_BUILD_KCSDR_SOURCE | ⛔ | ⛔ | ⛔ |
|
|
||||||
| limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ |
|
| limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ |
|
||||||
| network_source | Beta | - | OPT_BUILD_NETWORK_SOURCE | ✅ | ✅ | ✅ |
|
| network_source | Unfinished | - | OPT_BUILD_NETWORK_SOURCE | ✅ | ✅ | ⛔ |
|
||||||
| perseus_source | Beta | libperseus-sdr | OPT_BUILD_PERSEUS_SOURCE | ⛔ | ✅ | ✅ |
|
| perseus_source | Beta | libperseus-sdr | OPT_BUILD_PERSEUS_SOURCE | ⛔ | ✅ | ✅ |
|
||||||
| plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ |
|
| plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| rfnm_source | Beta | librfnm | OPT_BUILD_RFNM_SOURCE | ⛔ | ✅ | ✅ |
|
| rfnm_source | Beta | librfnm | OPT_BUILD_RFNM_SOURCE | ⛔ | ⛔ | ⛔ |
|
||||||
| rfspace_source | Working | - | OPT_BUILD_RFSPACE_SOURCE | ✅ | ✅ | ✅ |
|
| rfspace_source | Working | - | OPT_BUILD_RFSPACE_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ |
|
| rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| rtl_tcp_source | Working | - | OPT_BUILD_RTL_TCP_SOURCE | ✅ | ✅ | ✅ |
|
| rtl_tcp_source | Working | - | OPT_BUILD_RTL_TCP_SOURCE | ✅ | ✅ | ✅ |
|
||||||
@@ -341,9 +339,9 @@ Modules in beta are still included in releases for the most part but not enabled
|
|||||||
| sdrpp_server_source | Working | - | OPT_BUILD_SDRPP_SERVER_SOURCE | ✅ | ✅ | ✅ |
|
| sdrpp_server_source | Working | - | OPT_BUILD_SDRPP_SERVER_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| soapy_source | Deprecated | soapysdr | OPT_BUILD_SOAPY_SOURCE | ⛔ | ⛔ | ⛔ |
|
| soapy_source | Deprecated | soapysdr | OPT_BUILD_SOAPY_SOURCE | ⛔ | ⛔ | ⛔ |
|
||||||
| spectran_source | Unfinished | RTSA Suite | OPT_BUILD_SPECTRAN_SOURCE | ⛔ | ⛔ | ⛔ |
|
| spectran_source | Unfinished | RTSA Suite | OPT_BUILD_SPECTRAN_SOURCE | ⛔ | ⛔ | ⛔ |
|
||||||
| spectran_http_source | Beta | - | OPT_BUILD_SPECTRAN_HTTP_SOURCE | ✅ | ✅ | ✅ |
|
| spectran_http_source | Beta | - | OPT_BUILD_SPECTRAN_HTTP_SOURCE | ✅ | ✅ | ⛔ |
|
||||||
| spyserver_source | Working | - | OPT_BUILD_SPYSERVER_SOURCE | ✅ | ✅ | ✅ |
|
| spyserver_source | Working | - | OPT_BUILD_SPYSERVER_SOURCE | ✅ | ✅ | ✅ |
|
||||||
| usrp_source | Beta | libuhd | OPT_BUILD_USRP_SOURCE | ⛔ | ⛔ | ✅ |
|
| usrp_source | Beta | libuhd | OPT_BUILD_USRP_SOURCE | ⛔ | ⛔ | ⛔ |
|
||||||
|
|
||||||
## Sinks
|
## Sinks
|
||||||
|
|
||||||
@@ -352,22 +350,20 @@ Modules in beta are still included in releases for the most part but not enabled
|
|||||||
| android_audio_sink | Working | - | OPT_BUILD_ANDROID_AUDIO_SINK | ⛔ | ✅ | ✅ (Android only) |
|
| android_audio_sink | Working | - | OPT_BUILD_ANDROID_AUDIO_SINK | ⛔ | ✅ | ✅ (Android only) |
|
||||||
| audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ |
|
| audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ |
|
||||||
| network_sink | Working | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ |
|
| network_sink | Working | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ |
|
||||||
| new_portaudio_sink | Working | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
|
| new_portaudio_sink | Beta | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
|
||||||
| portaudio_sink | Working | portaudio | OPT_BUILD_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
|
| portaudio_sink | Beta | portaudio | OPT_BUILD_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
|
||||||
|
|
||||||
## Decoders
|
## Decoders
|
||||||
|
|
||||||
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|
||||||
|---------------------|------------|--------------|-------------------------------|:---------------:|:----------------:|:---------------------------:|
|
|---------------------|------------|--------------|-------------------------------|:---------------:|:----------------:|:---------------------------:|
|
||||||
| atv_decoder | Unfinished | - | OPT_BUILD_ATV_DECODER | ⛔ | ⛔ | ⛔ |
|
| atv_decoder | Unfinished | - | OPT_BUILD_ATV_DECODER | ⛔ | ⛔ | ⛔ |
|
||||||
| dab_decoder | Unfinished | - | OPT_BUILD_DAB_DECODER | ⛔ | ⛔ | ⛔ |
|
|
||||||
| falcon9_decoder | Unfinished | ffplay | OPT_BUILD_FALCON9_DECODER | ⛔ | ⛔ | ⛔ |
|
| falcon9_decoder | Unfinished | ffplay | OPT_BUILD_FALCON9_DECODER | ⛔ | ⛔ | ⛔ |
|
||||||
| kgsstv_decoder | Unfinished | - | OPT_BUILD_KGSSTV_DECODER | ⛔ | ⛔ | ⛔ |
|
| kgsstv_decoder | Unfinished | - | OPT_BUILD_KGSSTV_DECODER | ⛔ | ⛔ | ⛔ |
|
||||||
| m17_decoder | Working | - | OPT_BUILD_M17_DECODER | ⛔ | ✅ | ⛔ |
|
| m17_decoder | Working | - | OPT_BUILD_M17_DECODER | ⛔ | ✅ | ⛔ |
|
||||||
| meteor_demodulator | Working | - | OPT_BUILD_METEOR_DEMODULATOR | ✅ | ✅ | ⛔ |
|
| meteor_demodulator | Working | - | OPT_BUILD_METEOR_DEMODULATOR | ✅ | ✅ | ⛔ |
|
||||||
| pager_decoder | Unfinished | - | OPT_BUILD_PAGER_DECODER | ⛔ | ⛔ | ⛔ |
|
| pager_decoder | Unfinished | - | OPT_BUILD_PAGER_DECODER | ⛔ | ⛔ | ⛔ |
|
||||||
| radio | Working | - | OPT_BUILD_RADIO | ✅ | ✅ | ✅ |
|
| radio | Working | - | OPT_BUILD_RADIO | ✅ | ✅ | ✅ |
|
||||||
| radio | Unfinished | - | OPT_BUILD_VOR_RECEIVER | ⛔ | ⛔ | ⛔ |
|
|
||||||
| weather_sat_decoder | Unfinished | - | OPT_BUILD_WEATHER_SAT_DECODER | ⛔ | ⛔ | ⛔ |
|
| weather_sat_decoder | Unfinished | - | OPT_BUILD_WEATHER_SAT_DECODER | ⛔ | ⛔ | ⛔ |
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
@@ -420,8 +416,8 @@ If you still have an issue, please open an issue about it or ask on the discord.
|
|||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Feel free to submit band plans via the GitHub issue tracker.
|
Feel free to submit pull requests and report bugs via the GitHub issue tracker.
|
||||||
For code changes, please create a feature request instead.
|
I will soon publish a contributing.md listing the code style to use.
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
@@ -441,18 +437,15 @@ For code changes, please create a feature request instead.
|
|||||||
* Flinger Films
|
* Flinger Films
|
||||||
* [Frank Werner (HB9FXQ)](https://twitter.com/HB9FXQ)
|
* [Frank Werner (HB9FXQ)](https://twitter.com/HB9FXQ)
|
||||||
* gringogrigio
|
* gringogrigio
|
||||||
* Jandro
|
|
||||||
* Jeff Moe
|
* Jeff Moe
|
||||||
* Joe Cupano
|
* Joe Cupano
|
||||||
* KD1SQ
|
* KD1SQ
|
||||||
* Kezza
|
* Kezza
|
||||||
* Krys Kamieniecki
|
* Krys Kamieniecki
|
||||||
* Lee Donaghy
|
* Lee Donaghy
|
||||||
* Lee (KD1SQ)
|
* Lee KD1SQ
|
||||||
* .lozenge. (Hank Hill)
|
* .lozenge. (Hank Hill)
|
||||||
* Martin Herren (HB9FXX)
|
* Martin Herren (HB9FXX)
|
||||||
* NeoVilsonWong
|
|
||||||
* Nitin (VU2JEK)
|
|
||||||
* ON4MU
|
* ON4MU
|
||||||
* [Passion-Radio.com](https://passion-radio.com/)
|
* [Passion-Radio.com](https://passion-radio.com/)
|
||||||
* Paul Maine
|
* Paul Maine
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"name": "France",
|
"name": "France",
|
||||||
"country_name": "France",
|
"country_name": "France",
|
||||||
"country_code": "FR",
|
"country_code": "FR",
|
||||||
"author_name": "Fred F4EED, Armand31",
|
"author_name": "Fred F4EED",
|
||||||
"author_url": "http://f4eed.wordpress.com, https://github.com/Armand31",
|
"author_url": "http://f4eed.wordpress.com",
|
||||||
"bands": [
|
"bands": [
|
||||||
{
|
{
|
||||||
"name": "137KHz - Radioamateur",
|
"name": "137KHz - Radioamateur",
|
||||||
@@ -355,7 +355,7 @@
|
|||||||
"end": 54000000
|
"end": 54000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radiodiffusion - Bande FM",
|
"name": "Bande FM - Radiodif.",
|
||||||
"type": "broadcast",
|
"type": "broadcast",
|
||||||
"start": 80000000,
|
"start": 80000000,
|
||||||
"end": 108000000
|
"end": 108000000
|
||||||
@@ -396,12 +396,6 @@
|
|||||||
"start": 162362500,
|
"start": 162362500,
|
||||||
"end": 162587500
|
"end": 162587500
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Radiodiffusion - Bande DAB",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 174000000,
|
|
||||||
"end": 223000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Military Aviation",
|
"name": "Military Aviation",
|
||||||
"type": "military",
|
"type": "military",
|
||||||
@@ -414,12 +408,6 @@
|
|||||||
"start": 240000000,
|
"start": 240000000,
|
||||||
"end": 270000000
|
"end": 270000000
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Police (TETRAPOL)",
|
|
||||||
"type": "military",
|
|
||||||
"start": 380000000,
|
|
||||||
"end": 400000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "70cm - Radioamateur",
|
"name": "70cm - Radioamateur",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
@@ -432,24 +420,12 @@
|
|||||||
"start": 446000000,
|
"start": 446000000,
|
||||||
"end": 446200000
|
"end": 446200000
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TNT (DVB-T)",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 470000000,
|
|
||||||
"end": 694000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "23cm - Radioamateur",
|
"name": "23cm - Radioamateur",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 1240000000,
|
"start": 1240000000,
|
||||||
"end": 1300000000
|
"end": 1300000000
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Radiodiffusion - Bande DAB",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 1452000000,
|
|
||||||
"end": 1492000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "13cm - Radioamateur",
|
"name": "13cm - Radioamateur",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
|
|||||||
@@ -1,231 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Ireland",
|
|
||||||
"country_name": "Republic Of Ireland",
|
|
||||||
"country_code": "IE",
|
|
||||||
"author_name": "Oskar Dudek",
|
|
||||||
"author_url": "",
|
|
||||||
"bands": [
|
|
||||||
{
|
|
||||||
"name": "2200m Ham Band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 135700,
|
|
||||||
"end": 137800
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Long wave",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 148500,
|
|
||||||
"end": 282500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AM broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 531000,
|
|
||||||
"end": 1602000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "160m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 1810000,
|
|
||||||
"end": 2000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "120m SW broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 2300000,
|
|
||||||
"end": 2495000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "90m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 3200000,
|
|
||||||
"end": 3400000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "80m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 3500000,
|
|
||||||
"end": 3800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "75m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 3900000,
|
|
||||||
"end": 4000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "60m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 4750000,
|
|
||||||
"end": 5060000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "60m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5351500,
|
|
||||||
"end": 5366500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "49m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 5900000,
|
|
||||||
"end": 6200000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "40m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 7000000,
|
|
||||||
"end": 7200000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "40m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 7200000,
|
|
||||||
"end": 7450000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "31m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 9400000,
|
|
||||||
"end": 9900000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "30m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 10100000,
|
|
||||||
"end": 10150000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "25m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 11600000,
|
|
||||||
"end": 12100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "22m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 13570000,
|
|
||||||
"end": 13870000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "20m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 14000000,
|
|
||||||
"end": 14350000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "19m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 15100000,
|
|
||||||
"end": 15800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "17m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 18068000,
|
|
||||||
"end": 18168000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "16m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 17480000,
|
|
||||||
"end": 17900000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "15m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 18900000,
|
|
||||||
"end": 19020000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "15m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 21000000,
|
|
||||||
"end": 21450000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "13m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 21450000,
|
|
||||||
"end": 21850000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "12m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 24890000,
|
|
||||||
"end": 24990000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "11m SW Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 25670000,
|
|
||||||
"end": 26100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CB",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 26965000,
|
|
||||||
"end": 27405000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "10m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 28000000,
|
|
||||||
"end": 29700000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FM Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 87500000,
|
|
||||||
"end": 108000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Airband VOR/ILS",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 108000000,
|
|
||||||
"end": 117900000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Airband Voice",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 118000000,
|
|
||||||
"end": 137000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Polar orbiting satellites",
|
|
||||||
"type": "satellite",
|
|
||||||
"start": 137000000,
|
|
||||||
"end": 138000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "6m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 50000000,
|
|
||||||
"end": 52000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "4m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 70000000,
|
|
||||||
"end": 70500000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "2m ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 144000000,
|
|
||||||
"end": 146000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm ham band",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 430000000,
|
|
||||||
"end": 440000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ADS-B",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 1089000000,
|
|
||||||
"end": 1091000000
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"name": "Radionavigazione",
|
"name": "Radionavigazione",
|
||||||
"type": "marine",
|
"type": "marine",
|
||||||
"start": 11300,
|
"start": 11300,
|
||||||
"end": 148500
|
"end": 135500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 137kHz",
|
"name": "Radioamatori 137kHz",
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Radioamatori 80 m",
|
"name": "Radioamatori 80 m",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 3500000,
|
"start": 3600000,
|
||||||
"end": 3800000
|
"end": 3800000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
"end": 10100000
|
"end": 10100000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 30m",
|
"name": "30m - Radioamateur",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 10100000,
|
"start": 10100000,
|
||||||
"end": 10150000
|
"end": 10150000
|
||||||
@@ -308,7 +308,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Radioamatori 17 m",
|
"name": "Radioamatori 17 m",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 18069000,
|
"start": 18068000,
|
||||||
"end": 18168000
|
"end": 18168000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -420,10 +420,10 @@
|
|||||||
"end": 47000000
|
"end": 47000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 6m",
|
"name": "Radioamatori 9 m",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 50000000,
|
"start": 47000000,
|
||||||
"end": 51000000
|
"end": 52500000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Wind profiler",
|
"name": "Wind profiler",
|
||||||
@@ -446,19 +446,19 @@
|
|||||||
{
|
{
|
||||||
"name": "Radiodiffusione FM",
|
"name": "Radiodiffusione FM",
|
||||||
"type": "broadcast",
|
"type": "broadcast",
|
||||||
"start": 87500000,
|
"start": 80000000,
|
||||||
"end": 108000000
|
"end": 108000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VOR/ILS",
|
"name": "VOR/ILS",
|
||||||
"type": "aviation",
|
"type": "aviation",
|
||||||
"start": 108000000,
|
"start": 108000000,
|
||||||
"end": 117975000
|
"end": 118000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mobile aeronautico",
|
"name": "Mobile aeronautico",
|
||||||
"type": "aviation",
|
"type": "aviation",
|
||||||
"start": 117975000,
|
"start": 118000000,
|
||||||
"end": 137000000
|
"end": 137000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -471,7 +471,7 @@
|
|||||||
"name": "Radioamatori 2 m",
|
"name": "Radioamatori 2 m",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 144000000,
|
"start": 144000000,
|
||||||
"end": 146000000
|
"end": 148000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Telefonia satellitare",
|
"name": "Telefonia satellitare",
|
||||||
@@ -567,7 +567,7 @@
|
|||||||
"name": "Radioamatori 70 cm",
|
"name": "Radioamatori 70 cm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 435000000,
|
"start": 435000000,
|
||||||
"end": 438000000
|
"end": 436000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mobile o fisso privato",
|
"name": "Mobile o fisso privato",
|
||||||
@@ -645,13 +645,7 @@
|
|||||||
"name": "Radioamatori 23 cm",
|
"name": "Radioamatori 23 cm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 1240000000,
|
"start": 1240000000,
|
||||||
"end": 1245000000
|
"end": 1270000000
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radioamatori 23cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 1267000000,
|
|
||||||
"end": 1298000000
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Wind profiler",
|
"name": "Wind profiler",
|
||||||
@@ -801,7 +795,7 @@
|
|||||||
"name": "Radioamatori 13 cm",
|
"name": "Radioamatori 13 cm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 2300000000,
|
"start": 2300000000,
|
||||||
"end": 2450000000
|
"end": 2400000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ISM, SAP/SAB, 802.11",
|
"name": "ISM, SAP/SAB, 802.11",
|
||||||
@@ -833,6 +827,12 @@
|
|||||||
"start": 2900000000,
|
"start": 2900000000,
|
||||||
"end": 3400000000
|
"end": 3400000000
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Radioamatori 9 cm",
|
||||||
|
"type": "amateur",
|
||||||
|
"start": 3400000000,
|
||||||
|
"end": 3475000000
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Reti numeriche",
|
"name": "Reti numeriche",
|
||||||
"type": "comms",
|
"type": "comms",
|
||||||
@@ -858,21 +858,9 @@
|
|||||||
"end": 5650000000
|
"end": 5650000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 5cm",
|
"name": "Radioamatori 6 cm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 5650000000,
|
"start": 5650000000,
|
||||||
"end": 5670000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radioamatori 5cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5760000000,
|
|
||||||
"end": 5770000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radioamatori 5cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5830000000,
|
|
||||||
"end": 5850000000
|
"end": 5850000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -926,7 +914,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Radioamatori 3 cm",
|
"name": "Radioamatori 3 cm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 10300000000,
|
"start": 10000000000,
|
||||||
"end": 10500000000
|
"end": 10500000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1013,16 +1001,10 @@
|
|||||||
"start": 23150000000,
|
"start": 23150000000,
|
||||||
"end": 23338000000
|
"end": 23338000000
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Radioamatori 1,5cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 24000000000,
|
|
||||||
"end": 24050000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ISM, SRD e LPR",
|
"name": "ISM, SRD e LPR",
|
||||||
"type": "ism",
|
"type": "ism",
|
||||||
"start": 24050000000,
|
"start": 24000000000,
|
||||||
"end": 24450000000
|
"end": 24450000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1104,7 +1086,7 @@
|
|||||||
"end": 43500000000
|
"end": 43500000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 7mm",
|
"name": "Radioamatori 6 mm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 47000000000,
|
"start": 47000000000,
|
||||||
"end": 47200000000
|
"end": 47200000000
|
||||||
@@ -1148,7 +1130,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Radioamatori 4 mm",
|
"name": "Radioamatori 4 mm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 75500000000,
|
"start": 76500000000,
|
||||||
"end": 81500000000
|
"end": 81500000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1164,23 +1146,17 @@
|
|||||||
"end": 122250000000
|
"end": 122250000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 2,4mm",
|
"name": "Radioamatori 2,5 mm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 122500000000,
|
"start": 122250000000,
|
||||||
"end": 123000000000
|
"end": 123000000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 2,23mm",
|
"name": "Radioamatori 2 mm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
"start": 134000000000,
|
"start": 134000000000,
|
||||||
"end": 141000000000
|
"end": 141000000000
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Radioamatori 2,1mm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 142000000000,
|
|
||||||
"end": 144000000000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Radioamatori 1 mm",
|
"name": "Radioamatori 1 mm",
|
||||||
"type": "amateur",
|
"type": "amateur",
|
||||||
|
|||||||
@@ -1,549 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Republic of Korea",
|
|
||||||
"country_name": "Republic of Korea",
|
|
||||||
"country_code": "KR",
|
|
||||||
"author_name": "SeoyeonBae",
|
|
||||||
"author_url": "https://github.com/bsy0317",
|
|
||||||
"bands": [
|
|
||||||
{
|
|
||||||
"name": "Radio Navigation",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 8300,
|
|
||||||
"end": 14000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Coastal Telegraph",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 14000,
|
|
||||||
"end": 19950
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 19950,
|
|
||||||
"end": 20250
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Coastal Telegraph",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 20250,
|
|
||||||
"end": 70000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radio Navigation",
|
|
||||||
"type": "navigation",
|
|
||||||
"start": 70000,
|
|
||||||
"end": 160000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Radio Navigation",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 160000,
|
|
||||||
"end": 285000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Maritime Radiobeacon",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 285000,
|
|
||||||
"end": 325000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Radio Navigation",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 325000,
|
|
||||||
"end": 472000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 472000,
|
|
||||||
"end": 479000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "International Distress Safety Call",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 479000,
|
|
||||||
"end": 505000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Maritime Telegraph",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 505000,
|
|
||||||
"end": 526500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 526500,
|
|
||||||
"end": 1606500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radiobuoy",
|
|
||||||
"type": "navigation",
|
|
||||||
"start": 1606500,
|
|
||||||
"end": 1800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 1800000,
|
|
||||||
"end": 1825000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radiobuoy Control LORAN",
|
|
||||||
"type": "radiolocation",
|
|
||||||
"start": 1825000,
|
|
||||||
"end": 2000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radiobuoy",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 2000000,
|
|
||||||
"end": 2065000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Distress Call",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 2065000,
|
|
||||||
"end": 2107000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "International Distress Search and Rescue",
|
|
||||||
"type": "mobile",
|
|
||||||
"start": 2173500,
|
|
||||||
"end": 2190500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Road Management",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 2194000,
|
|
||||||
"end": 2495000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 2495000,
|
|
||||||
"end": 2505000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Telephone",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 2505000,
|
|
||||||
"end": 2850000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile R",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 2850000,
|
|
||||||
"end": 3025000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile OR",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 3025000,
|
|
||||||
"end": 3155000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile R",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 3400000,
|
|
||||||
"end": 3500000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 3500000,
|
|
||||||
"end": 3550000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Experimental Station",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 3550000,
|
|
||||||
"end": 3790000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 3790000,
|
|
||||||
"end": 3800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 3900000,
|
|
||||||
"end": 3950000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 3995000,
|
|
||||||
"end": 4005000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Telephone",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4005000,
|
|
||||||
"end": 4063000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Oceanographic Data",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4063000,
|
|
||||||
"end": 4065000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Duplex Telephone",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4065000,
|
|
||||||
"end": 4146000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Simplex Telephone",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4146000,
|
|
||||||
"end": 4152000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Wideband Telegraph Fax",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4152000,
|
|
||||||
"end": 4172000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station Narrowband",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4172000,
|
|
||||||
"end": 4181750
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ship Station A1A Morse Code Communication",
|
|
||||||
"type": "marine",
|
|
||||||
"start": 4186750,
|
|
||||||
"end": 4202250
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radiolocation",
|
|
||||||
"type": "radiolocation",
|
|
||||||
"start": 4438000,
|
|
||||||
"end": 4488000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Calling Response",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 4488000,
|
|
||||||
"end": 4650000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile R",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 4650000,
|
|
||||||
"end": 4850000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 4995000,
|
|
||||||
"end": 5005000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Search Rescue",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 5480000,
|
|
||||||
"end": 5730000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 5900000,
|
|
||||||
"end": 5950000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 5950000,
|
|
||||||
"end": 6200000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 7000000,
|
|
||||||
"end": 7100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 7100000,
|
|
||||||
"end": 7200000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 7200000,
|
|
||||||
"end": 7450000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 7995000,
|
|
||||||
"end": 8005000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 9400000,
|
|
||||||
"end": 9500000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 9500000,
|
|
||||||
"end": 9900000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 9995000,
|
|
||||||
"end": 10005000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 10100000,
|
|
||||||
"end": 10150000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 10150000,
|
|
||||||
"end": 11600000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 11600000,
|
|
||||||
"end": 11650000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 11650000,
|
|
||||||
"end": 12050000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 12050000,
|
|
||||||
"end": 12100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 13260000,
|
|
||||||
"end": 13360000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Radio Astronomy",
|
|
||||||
"type": "astronomy",
|
|
||||||
"start": 13360000,
|
|
||||||
"end": 13410000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 13570000,
|
|
||||||
"end": 13600000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 13600000,
|
|
||||||
"end": 13800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 13800000,
|
|
||||||
"end": 13870000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 14000000,
|
|
||||||
"end": 14350000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aviation Mobile",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 15010000,
|
|
||||||
"end": 15100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 15100000,
|
|
||||||
"end": 15600000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 15600000,
|
|
||||||
"end": 15800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 15800000,
|
|
||||||
"end": 15995000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Standard Frequency Time Signal",
|
|
||||||
"type": "utility",
|
|
||||||
"start": 15995000,
|
|
||||||
"end": 16005000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 18900000,
|
|
||||||
"end": 19020000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 21000000,
|
|
||||||
"end": 21450000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 21450000,
|
|
||||||
"end": 21850000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 24890000,
|
|
||||||
"end": 24990000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shortwave Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 25670000,
|
|
||||||
"end": 26100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 28000000,
|
|
||||||
"end": 29700000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 50000000,
|
|
||||||
"end": 54000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TV Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 54000000,
|
|
||||||
"end": 72000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Flood Warning",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 72000000,
|
|
||||||
"end": 74800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TV Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 76000000,
|
|
||||||
"end": 88000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FM Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 88000000,
|
|
||||||
"end": 100000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FM Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 100000000,
|
|
||||||
"end": 108000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ILS Localizer VOR",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 108000000,
|
|
||||||
"end": 117975000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Amateur Station",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 144000000,
|
|
||||||
"end": 146000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "General Communication",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 146000000,
|
|
||||||
"end": 148000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Low Power Device",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 162037500,
|
|
||||||
"end": 174000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TV Broadcast",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 174000000,
|
|
||||||
"end": 216000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Low Power Device",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 216000000,
|
|
||||||
"end": 230000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Low Power Device",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 273000000,
|
|
||||||
"end": 322000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Personal Radio",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 420000000,
|
|
||||||
"end": 470000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Public Network",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 698000000,
|
|
||||||
"end": 806000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Low Power Device",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 942000000,
|
|
||||||
"end": 960000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Satellite Mobile Communication",
|
|
||||||
"type": "fixed",
|
|
||||||
"start": 15250000000,
|
|
||||||
"end": 16605000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Mobile Communication",
|
|
||||||
"type": "mobile",
|
|
||||||
"start": 25000000000,
|
|
||||||
"end": 37000000000
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Turkey",
|
|
||||||
"country_name": "Turkey",
|
|
||||||
"country_code": "TR",
|
|
||||||
"author_name": "Yunus TA2PEA",
|
|
||||||
"author_url": "https://github.com/ycanerol",
|
|
||||||
"bands": [
|
|
||||||
{
|
|
||||||
"name": "LW",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 135700,
|
|
||||||
"end": 137800
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "630m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 472000,
|
|
||||||
"end": 479000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "160m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 1810000,
|
|
||||||
"end": 1850000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "80m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 3500000,
|
|
||||||
"end": 3800000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "60m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5351500,
|
|
||||||
"end": 5366500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "40m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 7000000,
|
|
||||||
"end": 7200000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "30m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 10100000,
|
|
||||||
"end": 10150000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "20m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 14000000,
|
|
||||||
"end": 14350000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "17m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 18068000,
|
|
||||||
"end": 18168000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "15m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 21000000,
|
|
||||||
"end": 21450000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "12m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 24890000,
|
|
||||||
"end": 24990000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CB",
|
|
||||||
"type": "other",
|
|
||||||
"start": 26565000,
|
|
||||||
"end": 27405000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Pagers",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 27750000,
|
|
||||||
"end": 28000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "10m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 28000000,
|
|
||||||
"end": 29700000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "6m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 50030000,
|
|
||||||
"end": 51000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FM",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 87500000,
|
|
||||||
"end": 108000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Airband VOR/ILS",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 108000000,
|
|
||||||
"end": 117975000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Airband Voice",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 117975000,
|
|
||||||
"end": 137000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "2m",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 144000000,
|
|
||||||
"end": 146000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Sayac Okuma",
|
|
||||||
"type": "other",
|
|
||||||
"start": 169400000,
|
|
||||||
"end": 169475000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Pagers",
|
|
||||||
"type": "other",
|
|
||||||
"start": 167000000,
|
|
||||||
"end": 167100000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Public announcement systems",
|
|
||||||
"type": "other",
|
|
||||||
"start": 173882500,
|
|
||||||
"end": 174000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DVB-T",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 174000000,
|
|
||||||
"end": 216000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "T-DAB",
|
|
||||||
"type": "broadcast",
|
|
||||||
"start": 216000000,
|
|
||||||
"end": 233000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ILS-Glide Path",
|
|
||||||
"type": "aviation",
|
|
||||||
"start": 328600000,
|
|
||||||
"end": 335400000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Public Safety/Emergency",
|
|
||||||
"type": "other",
|
|
||||||
"start": 380000000,
|
|
||||||
"end": 385000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Public Safety/Emergency",
|
|
||||||
"type": "other",
|
|
||||||
"start": 390000000,
|
|
||||||
"end": 395000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 430200000,
|
|
||||||
"end": 430700000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm-RepeaterRX",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 431550000,
|
|
||||||
"end": 431825000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 432000000,
|
|
||||||
"end": 432975000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 433400000,
|
|
||||||
"end": 434000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 435000000,
|
|
||||||
"end": 438000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "70cm-RepeaterTX",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 439150000,
|
|
||||||
"end": 439425000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Public announcement systems",
|
|
||||||
"type": "other",
|
|
||||||
"start": 445250000,
|
|
||||||
"end": 445462500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PMR446",
|
|
||||||
"type": "other",
|
|
||||||
"start": 446006250,
|
|
||||||
"end": 446196875
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "RFID",
|
|
||||||
"type": "other",
|
|
||||||
"start": 865000000,
|
|
||||||
"end": 868000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "RFID",
|
|
||||||
"type": "other",
|
|
||||||
"start": 916100000,
|
|
||||||
"end": 918900000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "23cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 1240000000,
|
|
||||||
"end": 1300000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DECT",
|
|
||||||
"type": "other",
|
|
||||||
"start": 1880000000,
|
|
||||||
"end": 1900000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "5GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5650000000,
|
|
||||||
"end": 5670000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "5GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 5820000000,
|
|
||||||
"end": 5850000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "3cm",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 104500000000,
|
|
||||||
"end": 104520000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "24GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 24000000000,
|
|
||||||
"end": 24050000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "47GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 47000000000,
|
|
||||||
"end": 47200000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "75GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 75500000000,
|
|
||||||
"end": 7600000000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "134GHz",
|
|
||||||
"type": "amateur",
|
|
||||||
"start": 134000000000,
|
|
||||||
"end": 142000000000
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user