diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e8311c..d58de9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,14 +52,13 @@ git_describe(GIT_TAG) find_package(LibSndFile REQUIRED) find_package(MBE REQUIRED) -find_package(ITPP REQUIRED) find_package(RTLSDR) find_package(Curses REQUIRED) find_package(PulseAudio REQUIRED) find_package(CODEC2) -include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIRS}) -set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${PULSEAUDIO_LIBRARY} ${CURSES_LIBRARIES}) +include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIRS}) +set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${PULSEAUDIO_LIBRARY} ${CURSES_LIBRARIES}) if(RTLSDR_FOUND) find_package(Threads) diff --git a/cmake/FindITPP.cmake b/cmake/FindITPP.cmake deleted file mode 100644 index d464252..0000000 --- a/cmake/FindITPP.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# - Try to find ITPP -# Once done this will define -# -# ITPP_FOUND - System has ITPP -# ITPP_INCLUDE_DIR - The ITPP include directory -# ITPP_LIBRARY - The library needed to use ITPP -# - -find_path(ITPP_INCLUDE_DIR itpp/itcomm.h) - -set(ITPP_NAMES ${ITPP_NAMES} itpp libitpp libitpp.dll) -FIND_LIBRARY(ITPP_LIBRARY NAMES ${ITPP_NAMES}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(ITPP DEFAULT_MSG ITPP_LIBRARY ITPP_INCLUDE_DIR) \ No newline at end of file diff --git a/cyg_portable.sh b/cyg_portable.sh index 4eb6707..1706a7f 100644 --- a/cyg_portable.sh +++ b/cyg_portable.sh @@ -98,7 +98,6 @@ if [ "$RELEASE" = "y" ]; then #compiled items into release dsd-fme folder cp codec2/build/src/cygcodec2* dsd-fme-portable/dsd-fme/ - cp itpp-4.3.1/build/itpp/cygitpp* dsd-fme-portable/dsd-fme/ cp rtl-sdr/build/src/cyg* dsd-fme-portable/dsd-fme/ cp mbelib/build/cygmbe* dsd-fme-portable/dsd-fme/ diff --git a/download-and-install-Arch.sh b/download-and-install-Arch.sh index 930d1c2..301f435 100644 --- a/download-and-install-Arch.sh +++ b/download-and-install-Arch.sh @@ -17,11 +17,6 @@ if [ "$ANSWER" = "y" ]; then sudo pacman -Syu #always run a full update first, partial upgrades aren't supported in Arch -- including downloading dependencies, that may require an updated dependency, and breaks same dependency on another package, a.k.a, dependency hell sudo pacman -S libpulse cmake ncurses lapack perl fftw rtl-sdr codec2 base-devel libsndfile git wget - printf "Installing itpp 4.3.1 from Arch Strike --Tested on Arch 2023.08.01 and Manjaro XFCE 22.1.3 Minimal\n" - wget https://mirror.archstrike.org/x86_64/archstrike/itpp-4.3.1-3-x86_64.pkg.tar.xz - sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz - sudo rm -R itpp-4.3.1-3-x86_64.pkg.tar.xz - git clone https://github.com/lwvmobile/mbelib cd mbelib git checkout ambe_tones diff --git a/download-and-install-cygwin.sh b/download-and-install-cygwin.sh index 5530962..c6f3021 100644 --- a/download-and-install-cygwin.sh +++ b/download-and-install-cygwin.sh @@ -19,22 +19,6 @@ if [ "$ANSWER" = "y" ]; then export LD_LIBRARY_PATH echo $LD_LIBRARY_PATH - #ITPP - cd $cdir - printf "Installing itpp 4.3.1 from source http://sourceforge.net/projects/itpp/files/latest/download?source=files\n Please wait!\n" - wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files - tar xjf itpp-latest.tar.bz2 - cd itpp-4.3.1/ - #newer Cygwin has Cmake 4.1.3 (or newer) so we need to replace the line with cmake_minimum_required to a newer version - #this doesn't seem to break anything, its just that cmake will refuse to run properly without a newer min version in it - #I'm just going to use the version that is used for most all my other cmake projects, seems to still be okay with new cmake - sed -i '/^cmake_minimum_required *( *VERSION *2\.8\.6 *)$/c\cmake_minimum_required(VERSION 3.10.2)' CMakeLists.txt - mkdir build - cd build - cmake .. - make -j $(nproc) - make install - #MBELIB cd $cdir printf "Installing mbelib\n Please wait!\n" diff --git a/download-and-install-ubuntu2404lts.sh b/download-and-install-ubuntu2404lts.sh index 43cc95c..fe2ca81 100644 --- a/download-and-install-ubuntu2404lts.sh +++ b/download-and-install-ubuntu2404lts.sh @@ -12,13 +12,7 @@ read -p "Have you viewed the patent notice? y/N " ANSWER ANSWER=$(printf "$ANSWER"|tr '[:upper:]' '[:lower:]') if [ "$ANSWER" = "y" ]; then sudo apt update - sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncurses-dev libncurses6 libcodec2-dev - chkitpp=$(dpkg -l libitpp-dev 2>/dev/null | awk '/^ii/ {print 1} END {if (NR == 0) print 0}') - if [ "$chkitpp" -lt "1" ];then - printf "\nFor some reason, ITPP did NOT install!\nYou may have to manually install it.\n\n" - read -p "Press Enter to exit..." x - exit 1 - fi + sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncurses-dev libncurses6 libcodec2-dev git clone https://github.com/lwvmobile/mbelib cd mbelib git checkout ambe_tones diff --git a/download-and-install.sh b/download-and-install.sh index c134797..3a40b31 100644 --- a/download-and-install.sh +++ b/download-and-install.sh @@ -12,13 +12,7 @@ read -p "Have you viewed the patent notice? y/N " ANSWER ANSWER=$(printf "$ANSWER"|tr '[:upper:]' '[:lower:]') if [ "$ANSWER" = "y" ]; then sudo apt update - sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev libcodec2-dev - chkitpp=$(dpkg -l libitpp-dev 2>/dev/null | awk '/^ii/ {print 1} END {if (NR == 0) print 0}') - if [ "$chkitpp" -lt "1" ];then - printf "\nFor some reason, ITPP did NOT install!\nYou may have to manually install it.\n\n" - read -p "Press Enter to exit..." x - exit 1 - fi + sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncursesw5-dev libcodec2-dev git clone https://github.com/lwvmobile/mbelib cd mbelib git checkout ambe_tones diff --git a/examples/Install_Notes.md b/examples/Install_Notes.md index f857a50..f611ebf 100644 --- a/examples/Install_Notes.md +++ b/examples/Install_Notes.md @@ -43,9 +43,9 @@ Debian/Mint/Ubuntu/Pi ``` sudo apt update #Ubuntu 22.04 lts / Debian 11 and lower -sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libcodec2-dev +sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libcodec2-dev #Ubuntu 24.04 lts / Debian 12 -#sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncurses-dev libncurses6 libcodec2-dev +#sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncurses-dev libncurses6 libcodec2-dev ``` Fedora 36/37 -- from https://github.com/lwvmobile/dsd-fme/issues/99 @@ -60,8 +60,6 @@ Arch -- https://github.com/lwvmobile/dsd-fme/issues/153 and https://github.com/l ``` sudo pacman -Syu sudo pacman -S libpulse cmake ncurses lapack perl fftw rtl-sdr codec2 base-devel libsndfile git wget rtl-sdr -wget https://mirror.archstrike.org/x86_64/archstrike/itpp-4.3.1-3-x86_64.pkg.tar.xz -sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz ``` ## Headless Ubuntu Server/Pi @@ -69,24 +67,7 @@ sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz If running headless, swap out pavucontrol for pulsemixer, and also install pulseaudio as well. Attempting to install pavucontrol in a headless environment may attempt to install a minimal desktop environment. Note: Default behavior of pulseaudio in a headless environment may be to be muted, so check by opening pulsemixer and unmuting and routing audio appropriately. ``` -sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev pulsemixer pulseaudio libcodec2-dev -``` - -### Build and Install ITPP - ONLY IF NOT IN REPO!! - -``` -wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files -tar xjf itpp* -#if you can't cd into this folder, double check folder name first -cd itpp-4.3.1 -mkdir build -cd build -cmake .. -make -j `nproc` -sudo make install -sudo ldconfig -cd .. -cd .. +sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncursesw5-dev pulsemixer pulseaudio libcodec2-dev ``` MBELib is considered a requirement in this build. You must read this notice prior to continuing. [MBElib Patent Notice](https://github.com/lwvmobile/mbelib#readme "MBElib Patent Notice") diff --git a/include/Golay24.hpp b/include/Golay24.hpp index 0731024..944ce29 100644 --- a/include/Golay24.hpp +++ b/include/Golay24.hpp @@ -7,8 +7,6 @@ * * Code adapted from http://www.aqdi.com/golay.htm * - * Tried before with the implementation from ITPP library but couldn't make it produce the same outputs - * expected from the P25 transmissions that I have tested. This implementation does work. */ #include diff --git a/include/ReedSolomon.hpp b/include/ReedSolomon.hpp index 49fbecc..a10d030 100644 --- a/include/ReedSolomon.hpp +++ b/include/ReedSolomon.hpp @@ -5,9 +5,6 @@ /** * Code taken and adapted from www.eccpage.com/rs.c * Credit goes to Mr Simon Rockliff. - * - * Tried before with the implementation from ITPP library but couldn't make it produce the same outputs - * expected from the P25 transmissions that I have tested. This implementation does work. */ /* This program is an encoder/decoder for Reed-Solomon codes. Encoding is in diff --git a/include/dsd.h b/include/dsd.h index 97d6b26..9f10c01 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -1671,6 +1671,9 @@ int ez_rs28_facch (int payload[156], int parity[114]); //ezpwd bridge for FME int ez_rs28_sacch (int payload[180], int parity[132]); //ezpwd bridge for FME int isch_lookup (uint64_t isch); //isch map lookup +//Phase 1 NID Check +int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity); + #ifdef __cplusplus } #endif diff --git a/include/p25p1_check_nid.h b/include/p25p1_check_nid.h deleted file mode 100644 index 28e83e0..0000000 --- a/include/p25p1_check_nid.h +++ /dev/null @@ -1,26 +0,0 @@ - -#ifndef P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a -#define P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Checks a NID value, returns the fixed NAC, DUID and also an indication if it failed to decode the NID. - * \param bch_code Input. An array to the 63 bytes, each containing one bit of the NID. This includes the - * NAC (12 bits), DUID (4 bits) and 47 bits of BCH parity. - * \param new_nac Output. An address where to store the calculated NAC value after error correction. Should - * be large enough to accommodate for an integer. - * \param new_duid Output. An address where to store the calculated DUID value after error correction. Should - * be able to accommodate 3 chars. - * \param parity Input. The parity value read. - * \return 0 if there were errors processing the NID. - */ -int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity); - -#ifdef __cplusplus -} -#endif - -#endif // P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a diff --git a/package.nix b/package.nix index ea1bd76..5bdd238 100644 --- a/package.nix +++ b/package.nix @@ -6,7 +6,6 @@ , ncurses , pulseaudio , rtl-sdr -, itpp , codec2 , portaudioSupport ? true , portaudio ? null @@ -23,7 +22,6 @@ stdenv.mkDerivation { buildInputs = [ mbelib libsndfile - itpp rtl-sdr ncurses.dev pulseaudio.dev @@ -39,7 +37,7 @@ stdenv.mkDerivation { tap audio and synthesize the decoded speech. Speech synthesis requires mbelib, which is a separate package. ''; - homepage = "https://github.com/szechyjs/dsd"; + homepage = "https://github.com/lwvmobile/dsd-fme"; license = licenses.mit; platforms = platforms.unix; }; diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 5986711..89d856a 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -20,8 +20,6 @@ #define NULL 0 #endif -#include "p25p1_check_nid.h" - void printFrameInfo (dsd_opts * opts, dsd_state * state) { diff --git a/src/p25p1_check_nid.cpp b/src/p25p1_check_nid.cpp index 33b01cc..2cc9f68 100644 --- a/src/p25p1_check_nid.cpp +++ b/src/p25p1_check_nid.cpp @@ -1,17 +1,138 @@ -#include +// BCH decoder implementation from OP25 (Copyright 2010, KA1RBI, GPL license) +#include "dsd.h" -#include "p25p1_check_nid.h" +#include +typedef std::vector bit_vector; +static const int bchGFexp[64] = { + 1, 2, 4, 8, 16, 32, 3, 6, 12, 24, 48, 35, 5, 10, 20, 40, + 19, 38, 15, 30, 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, 51, 37, + 9, 18, 36, 11, 22, 44, 27, 54, 47, 29, 58, 55, 45, 25, 50, 39, + 13, 26, 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, 57, 49, 33, 0 +}; +static const int bchGFlog[64] = { + -1, 0, 1, 6, 2, 12, 7, 26, 3, 32, 13, 35, 8, 48, 27, 18, + 4, 24, 33, 16, 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, 19, 56, + 5, 62, 25, 11, 34, 31, 17, 47, 15, 23, 53, 51, 37, 44, 55, 40, + 10, 61, 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, 20, 59, 57, 58 +}; -using namespace itpp; +int bchDec(bit_vector& Codeword) +{ + int elp[24][22], S[23]; + int D[23], L[24], uLu[24]; + int locn[11], reg[12]; + int i, j, U, q, count; + int SynError, CantDecode; -// Ideas taken from http://op25.osmocom.org/trac/wiki.png/browser/op25/gr-op25/lib/decoder_ff_impl.cc -// See also p25_training_guide.pdf page 48. -// See also tia-102-baaa-a-project_25-fdma-common_air_interface.pdf page 40. -// BCH encoder/decoder implementation from IT++. GNU GPL 3 license. + SynError = 0; CantDecode = 0; -itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true); + for (i = 1; i <= 22; i++) { + S[i] = 0; + for (j = 0; j <= 62; j++) { + if (Codeword[j]) { + S[i] = S[i] ^ bchGFexp[(i * j) % 63]; + } + } + if (S[i]) { SynError = 1; } + S[i] = bchGFlog[S[i]]; + } + + if (SynError) { // if there are errors, try to correct them + L[0] = 0; uLu[0] = -1; D[0] = 0; elp[0][0] = 0; + L[1] = 0; uLu[1] = 0; D[1] = S[1]; elp[1][0] = 1; + for (i = 1; i <= 21; i++) { + elp[0][i] = -1; elp[1][i] = 0; + } + U = 0; + + do { + U = U + 1; + if (D[U] == -1) { + L[U + 1] = L[U]; + for (i = 0; i <= L[U]; i++) { + elp[U + 1][i] = elp[U][i]; + elp[U][i] = bchGFlog[elp[U][i]]; + } + } else { + q = U - 1; + while ((D[q] == -1) && (q > 0)) { q = q - 1; } + if (q > 0) { + j = q; + do { j = j - 1; if ((D[j] != -1) && (uLu[q] < uLu[j])) { q = j; } + } while (j > 0); + } + + if (L[U] > L[q] + U - q) { + L[U + 1] = L[U]; + } else { + L[U + 1] = L[q] + U - q; + } + + for (i = 0; i <= 21; i++) { + elp[U + 1][i] = 0; + } + for (i = 0; i <= L[q]; i++) { + if (elp[q][i] != -1) { + elp[U + 1][i + U - q] = bchGFexp[(D[U] + 63 - D[q] + elp[q][i]) % 63]; + } + } + for (i = 0; i <= L[U]; i++) { + elp[U + 1][i] = elp[U + 1][i] ^ elp[U][i]; + elp[U][i] = bchGFlog[elp[U][i]]; + } + } + uLu[U + 1] = U - L[U + 1]; + + if (U < 22) { + if (S[U + 1] != -1) { D[U + 1] = bchGFexp[S[U + 1]]; } else { D[U + 1] = 0; } + for (i = 1; i <= L[U + 1]; i++) { + if ((S[U + 1 - i] != -1) && (elp[U + 1][i] != 0)) { + D[U + 1] = D[U + 1] ^ bchGFexp[(S[U + 1 - i] + bchGFlog[elp[U + 1][i]]) % 63]; + } + } + D[U + 1] = bchGFlog[D[U + 1]]; + } + } while ((U < 22) && (L[U + 1] <= 11)); + + U = U + 1; + if (L[U] <= 11) { + for (i = 0; i <= L[U]; i++) { + elp[U][i] = bchGFlog[elp[U][i]]; + } + + for (i = 1; i <= L[U]; i++) { + reg[i] = elp[U][i]; + } + count = 0; + for (i = 1; i <= 63; i++) { + q = 1; + for (j = 1; j <= L[U]; j++) { + if (reg[j] != -1) { + reg[j] = (reg[j] + j) % 63; + q = q ^ bchGFexp[reg[j]]; + } + } + if (q == 0) { + locn[count] = 63 - i; + count = count + 1; + } + } + if (count == L[U]) { + for (i = 0; i <= L[U] - 1; i++) { + Codeword[locn[i]] = Codeword[locn[i]] ^ 1; + } + CantDecode = count; + } else { + CantDecode = -1; + } + } else { + CantDecode = -2; + } + } + return CantDecode; +} /** * Convenience class to calculate the parity of the DUID values. Keeps a table with the expected outcomes @@ -24,13 +145,13 @@ private: unsigned char get_index(unsigned char x, unsigned char y) { - return (x<<2) + y; + return (x << 2) + y; } public: ParityTable() { - for (unsigned int i=0; i= 0); if (!ok) { // Decode failed + // fprintf (stderr, "NID ERR: %d; ", errors); result = 0; } else { + //reload the codeword back into correct bit order + for (unsigned int i = 0; i < 63; i++) { + bch_code[i] = codeword[62-i]; + } + for (unsigned int i = 0; i < 63; i++) { + codeword[i] = bch_code[i]; + } // Take the NAC from the decoded output. It's a 12 bit number starting from position 0. - // Just convert the output from a binary sequence to an integer. int nac = 0; - for (int i=0; i<12; i++) { + for (int i = 0; i < 12; i++) { nac <<= 1; - nac |= (int)decoded[i]; + nac |= (int)codeword[i]; } *new_nac = nac; // Take the fixed DUID from the encoded output. 4 bit value starting at position 12. - unsigned char new_duid_0 = (((int)decoded[12])<<1) + ((int)decoded[13]); - unsigned char new_duid_1 = (((int)decoded[14])<<1) + ((int)decoded[15]); + unsigned char new_duid_0 = (((int)codeword[12]) << 1) + ((int)codeword[13]); + unsigned char new_duid_1 = (((int)codeword[14]) << 1) + ((int)codeword[15]); new_duid[0] = new_duid_0 + '0'; new_duid[1] = new_duid_1 + '0'; new_duid[2] = 0; // Null terminate @@ -82,12 +209,12 @@ int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity unsigned char expected_parity = parity_table.get_value(new_duid_0, new_duid_1); if (expected_parity != parity) { - // Ignore, not sure what to do - //fprintf (stderr, "Error in parity detected?"); + // Parity mismatch – optional handling + // fprintf(stderr, "Error in parity detected?\n"); } result = 1; } return result; -} +} \ No newline at end of file