95 Commits

Author SHA1 Message Date
lwvmobile
ae58fabb72 DMR Cap+ Block Counter Fix; #126 2023-05-15 02:54:09 -04:00
lwvmobile
e390251b9d Tweaks to NXDN FSW Tests II; #123 2023-05-14 13:54:48 -04:00
lwvmobile
f7ad3e638f Ncurses No Color Trunking Tweaks; #114 2023-05-13 20:11:36 -04:00
lwvmobile
a16c99994c Misc Tweaks and Clear Stale Active Ch Values; #120 2023-05-13 01:39:23 -04:00
lwvmobile
7f187ff6d8 Fix LimaZulu NXDN Tweaks #123 2023-05-12 02:44:16 -04:00
lwvmobile
8485be965b Tweaks to NXDN FSW Tests; #123 2023-05-05 18:30:06 -04:00
lwvmobile
d1e1572139 pV Conventional Frame Sync and pV Tweaks; #122 2023-05-05 06:33:29 -04:00
lwvmobile
95e74c8e28 NXDN Frame Sync Tests and Cmake Option #123 2023-05-05 06:14:56 -04:00
lwvmobile
815fbb026f Various uint64_t/ul/ulli fixes for 32-bit; 2023-05-04 23:58:44 -04:00
lwvmobile
d1ce0121be Misc Tweaks and Fixes; Glamor Shots; 2023-05-03 23:44:57 -04:00
lwvmobile
a55db055d4 NCURSES Active Ch Display Tweaks; #120 2023-05-02 18:34:31 -04:00
lwvmobile
443b7c3031 DMR Active Channel Display; CSBK Tweaks; #120 2023-05-02 18:31:59 -04:00
lwvmobile
4bebb361ec P25 ENC Trunk Toggle and Active Tweaks; #120 #121 2023-05-02 18:25:25 -04:00
lwvmobile
6f538fd166 Active Channel Display NXDN Setup and Misc; #120 2023-05-02 18:19:41 -04:00
lwvmobile
fef36e3761 NXDN Tweaks to clear stale key values on keyload; 2023-04-29 17:01:16 -04:00
lwvmobile
19df3dd7f1 TCP Audio Retry on Disc; Ncurses Key '8'; #119 2023-04-29 16:06:22 -04:00
lwvmobile
acd2b0b134 More NXDN/IDAS Tweaks and Fixes; #115 and #118 2023-04-25 15:37:44 -04:00
lwvmobile
0908baa47c Update Literature; 2023-04-23 20:02:02 -04:00
lwvmobile
c507ed229c NXDN Type-D Decoding/Trunking; NXDN Tweaks; #115 2023-04-23 19:52:32 -04:00
lwvmobile
3101bbde28 Cap Plus Expansion; Minor DMR Tweaks; #116 2023-04-23 19:50:01 -04:00
lwvmobile
5e24ff505d Initial NXDN Type D - 'IDAS' Support; #115 2023-04-13 18:19:25 -04:00
lwvmobile
4a8bf144dd Literature Update; 2023-04-13 12:22:50 -04:00
lwvmobile
d872818e03 NXDN Array Expansion and Message Tweaks; #113 2023-04-13 11:00:28 -04:00
lwvmobile
f967b80217 No Color Cmake Build Option #114 2023-04-13 10:59:40 -04:00
lwvmobile
f3d94ddc2a More XPT Work; #110 2023-04-12 17:53:34 -04:00
lwvmobile
18bec720ae Hashed DMR TG Multi Key Loading Fix; #112 2023-04-12 13:10:11 -04:00
lwvmobile
456687ba86 pacmd to pactl in virtualsink; #111 2023-04-09 14:29:50 -04:00
lwvmobile
ba0e422f23 Hytera XPT WIP #110 2023-04-08 19:14:47 -04:00
lwvmobile
ce75acb41a Yet Another Cmake Warning Fix #107 2023-03-28 23:32:00 -04:00
lwvmobile
68862296bf NXDN -- DFA Base Freq Fix; ADJ_SITE_INFO; #106 2023-03-28 17:29:59 -04:00
lwvmobile
f3c0199b32 Issue #105 - Make Work with Named Pipe (FIFO) 2023-03-22 20:03:39 -04:00
lwvmobile
c8e8e041b7 NXDN DFA Support; Update Literature; 2023-03-22 20:00:14 -04:00
lwvmobile
85eea59598 Fix Cmake Warnings; 2023-03-21 22:33:42 -04:00
lwvmobile
304b5545ba Issue #105 Segfault Bugfix; 2023-03-21 20:59:53 -04:00
lwvmobile
313759333e P2 - TDMA-CC Tuning Bugfix and callstring tweak; 2023-03-21 20:58:37 -04:00
lwvmobile
1737c1f7e9 NXDN48/96 Tweak; 2023-03-12 15:41:27 -04:00
lwvmobile
bd94f83318 More XPT Tweaks and Notes; 2023-03-09 18:54:03 -05:00
lwvmobile
5d7988ea0f Line Space OCD; 2023-03-09 18:40:32 -05:00
lwvmobile
432495c1ad P25 P1 LCW re-write and updates; 2023-03-08 02:07:26 -05:00
lwvmobile
9c75583323 NCurses LO Return to CC; 2023-03-08 02:04:54 -05:00
lwvmobile
b9389742f6 XPT Trunking Tweak; 2023-03-08 02:04:05 -05:00
lwvmobile
fb59406a28 P25 P1 QPSK MSIZE/SSIZE Tweak; 2023-03-08 02:02:53 -05:00
lwvmobile
339323695f Update Literature; 2023-03-08 02:01:49 -05:00
lwvmobile
d8e7c4c3aa Fix trunk_hangtime lf to f; Ncurses Fixes; 2023-03-06 03:07:23 -05:00
lwvmobile
1dc6737cc2 Fix Fast Scanner and NCurses Display (again) 2023-03-05 05:52:41 -05:00
lwvmobile
c1ed3fe038 Fix unintended bug in iden_up_vu; 2023-03-04 20:52:59 -05:00
lwvmobile
d86b370a22 Literature Update 2023-03-04 19:27:36 -05:00
lwvmobile
b7bfa98a50 P25 TSBK PDU Fix; vPDU PDU Fixes; Scanner Freq Fix 2023-03-04 19:26:35 -05:00
lwvmobile
da41dcd5c9 Fast Scan Ncurses Tweak; Update Literature; 2023-03-03 15:36:10 -05:00
lwvmobile
0c27de102d P25 - P1 MBF Format Addition; TSBK/vPDU Tweaks; 2023-03-03 15:15:31 -05:00
lwvmobile
54c75e20c9 NXDN Trunking Tweaks and Misc Tweaks; 2023-03-02 22:13:45 -05:00
lwvmobile
3102770353 Trunking -- Faster CC Hunt; 2023-03-01 18:32:26 -05:00
lwvmobile
477ca97830 Experimental -- Fast Scanner Feature; 2023-03-01 17:56:07 -05:00
lwvmobile
5b51adfc95 P25 - Remove Test Code; NXDN - Remove Freq Calc; 2023-03-01 17:49:37 -05:00
lwvmobile
4ab16b5935 DMR - XPT Tweaks; Data Header Tweaks; 2023-02-25 16:07:01 -05:00
lwvmobile
fe5ec8b0b4 FID 0x10 - FLCO 0x14, 0x15, 0x16, 0x17, 0x18; 2023-02-24 20:51:37 -05:00
lwvmobile
58d8ad8a8c Disable remaining setmod_bw as safety precaution; 2023-02-24 20:46:31 -05:00
lwvmobile
df5d755345 NXDN Trunking Tweak - Snap Back to CC on Disc; 2023-02-24 18:40:59 -05:00
lwvmobile
9a7a836eca Fix P_Protect CSBK GI indicator; 2023-02-24 18:40:07 -05:00
lwvmobile
4243fc9692 Fix NCurses **tera key display when loaded; 2023-02-24 18:38:55 -05:00
lwvmobile
c999c97445 Misc Tweaks; Multi BP; More CapMax FLCO; XPT; 2023-02-23 21:57:49 -05:00
lwvmobile
569f72508a Literature Update; 2023-02-22 20:28:03 -05:00
lwvmobile
d78f516afe NXDN Tweaks and SACCH/FACCH CRC Fixes; 2023-02-22 19:46:03 -05:00
lwvmobile
6e4a373d26 Minor Cap+ and XPT Fix; 2023-02-20 22:42:36 -05:00
lwvmobile
2f644f5ba6 Disable/Tweak some setmod_bw defaults; 2023-02-20 17:58:48 -05:00
lwvmobile
37c24d0ca7 Cap+ NL; Hytera XPT Trunk Support (experimental) 2023-02-20 12:46:23 -05:00
lwvmobile
9cdbd35e51 General DMR Tweaks; 64-bit IV from 32-bit MI; 2023-02-20 12:43:14 -05:00
lwvmobile
67e28c4655 DMR - LRRP tweaks; Add LOCN PDU. 2023-02-20 12:41:17 -05:00
lwvmobile
591df8657a DMR - dheader rewrite; UDT/USBD fix; block tweaks; 2023-02-20 12:40:39 -05:00
lwvmobile
c708ea5911 P25 Dibit, Block and PDU Payload Tweaks; 2023-02-20 12:35:40 -05:00
lwvmobile
a4ecfdca30 DMR - Fix Cap+ CSBK; Various Minor Fixes; 2023-02-05 16:46:02 -05:00
lwvmobile
ac1fd7897c DMR Minor Code Fixes; 2023-02-04 20:09:54 -05:00
lwvmobile
a02f992a25 NCurses Compiler Warning and Call Alert Fix; 2023-02-04 04:34:09 -05:00
lwvmobile
630d3f362c DMR Cap+ CSBK Improvements; 2023-02-03 22:12:48 -05:00
lwvmobile
6666424ff8 DMR FLCO Tweaks; P25 Site/RFSS Display; 2023-02-02 20:02:28 -05:00
lwvmobile
b0fc20cea6 DMR Conf Data CRC9; Message CRC32; Tweaks; 2023-02-01 05:35:15 -05:00
lwvmobile
f61dbd4fe7 DMR FLC Tweaks; CSBK Cleaning; 2023-02-01 05:31:36 -05:00
lwvmobile
f369d645b1 DMR FLCO - Check PF First; 2023-01-29 16:09:44 -05:00
lwvmobile
7148e653e5 DMR Unknown FLCO Tweaks; PI Tweaks; 2023-01-28 21:00:08 -05:00
lwvmobile
bb5da93fcd Fix DMR FEC/CRC/RAS Implementation Issues; 2023-01-21 05:41:22 -05:00
lwvmobile
d2d750e920 Tweak RAS/CRC; Other Misc Tweaks; 2023-01-19 09:39:05 -05:00
lwvmobile
485161f42d NXDN Multi-Key CSV Import; Example Updt; 2023-01-18 12:18:48 -05:00
lwvmobile
67661c2fb0 DMR SB/RC Additions; Cap+ LC/CSBK; RAS; 2023-01-17 23:57:58 -05:00
lwvmobile
dcb21f2cd0 Fix/Restore MBEout Files; 'DSP' CACH; Tweaks; 2023-01-17 02:24:49 -05:00
lwvmobile
9f03bbc8a1 Cap+ FLC/CSBK Tweaks; 2023-01-17 02:08:21 -05:00
lwvmobile
b4ecdf7820 'DSP' File Output for OKDMR - Initial Commit; 2023-01-15 22:03:53 -05:00
lwvmobile
35cc358101 Cap+ Things; 2023-01-15 21:22:18 -05:00
lwvmobile
db23968a6f Allow Standard BP Key on MBE File Playback; 2023-01-15 18:13:39 -05:00
lwvmobile
9efd950b9f Fix Audio Gain on MBE File Playback; 2023-01-15 18:11:34 -05:00
lwvmobile
08461492ee P25 P2 ISCH Var Fix; 2023-01-15 18:09:25 -05:00
lwvmobile
b2ccd3a878 DMR Cap+ Rest Channel FLCO/SLCO Fix; 2023-01-09 19:35:03 -05:00
lwvmobile
9b8a382ea5 RTL Tuning Fix(UDP); Cosmetic Change; 2023-01-09 13:19:34 -05:00
lwvmobile
235eeedcda dPMR 'Version' Check Fix; 2023-01-07 15:16:52 -05:00
lwvmobile
0cff92101c dPMR Scrambler Key Support; 2023-01-07 15:02:04 -05:00
lwvmobile
c44e039772 EDACS 32-bit Variable Fix; 2023-01-05 16:27:44 -05:00
53 changed files with 2174 additions and 5832 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ build
examples examples
*.bin *.bin
*.ans *.ans

View File

@@ -1,6 +1,6 @@
#Ubuntu 20.04 uses 3.16.3 #Ubuntu 20.04 uses 3.16.3
#Ubuntu 22.04 uses 3.22.1 #Ubuntu 22.04 uses 3.22.1
#Arch currently on 3.26.3 #Arch currently on 3.26.3
#Cygwin currently using 3.23.2 (or newer) #Cygwin currently using 3.23.2 (or newer)
cmake_minimum_required(VERSION 3.10.2) cmake_minimum_required(VERSION 3.10.2)
project(dsd-fme) project(dsd-fme)
@@ -10,13 +10,6 @@ SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
set(CURSES_NEED_NCURSES TRUE) set(CURSES_NEED_NCURSES TRUE)
set(CURSES_NEED_WIDE TRUE) set(CURSES_NEED_WIDE TRUE)
#use cmake option -DAERO=ON to enable Aero Builds (OSS support and specific tweaks)
option(AERO
"Build for Aero Environments (Cygwin)" OFF)
if (AERO)
add_definitions(-DAERO_BUILD)
endif ()
#use cmake option -DCOLORS=OFF to disable color output #use cmake option -DCOLORS=OFF to disable color output
option(COLORS option(COLORS
"Build with Colors Enabled" ON) "Build with Colors Enabled" ON)
@@ -31,11 +24,11 @@ if (PVC)
add_definitions(-DPVCONVENTIONAL) add_definitions(-DPVCONVENTIONAL)
endif () endif ()
#use cmake option -DNXDN=ON to enable the old NXDN Sync Pattern #use cmake option -DNXDN=ON to enable new NXDN Sync Pattern Testing
option(NXDN option(NXDN
"Build with Old NXDN Sync Pattern Enabled" OFF) "Build with new NXDN Sync Pattern Testing Enabled" OFF)
if (NXDN) if (NXDN)
add_definitions(-DNXDNOLDSYNC) add_definitions(-DNXDNTESTSYNC)
endif () endif ()
#use cmake option -DLZ=ON to enable LimaZulu Requested NXDN Tweaks #use cmake option -DLZ=ON to enable LimaZulu Requested NXDN Tweaks
@@ -45,20 +38,6 @@ if (LZ)
add_definitions(-DLIMAZULUTWEAKS) add_definitions(-DLIMAZULUTWEAKS)
endif () endif ()
#use cmake option -DTONES to change default location of the tones.wav files (lwvmobile precompiled 'Aero' releases only)
option(TN
"Build with tone wav files in the dsd-fme folder and not in /usr/share/" OFF)
if (TN)
add_definitions(-DTONES)
endif ()
#use cmake option -DZDEV to change designation of this build from MAIN to zDEV
option(ZDEV
"change designation of this build from MAIN to zDEV" OFF)
if (ZDEV)
add_definitions(-DZDEV_BUILD)
endif ()
include(git_revision) include(git_revision)
git_describe(GIT_TAG) git_describe(GIT_TAG)
@@ -68,7 +47,6 @@ find_package(ITPP REQUIRED)
find_package(RTLSDR) find_package(RTLSDR)
find_package(Curses REQUIRED) find_package(Curses REQUIRED)
find_package(PulseAudio 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_DIR}) include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR})
set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY})
@@ -80,12 +58,6 @@ if(RTLSDR_FOUND)
add_definitions(-DUSE_RTLSDR) add_definitions(-DUSE_RTLSDR)
endif(RTLSDR_FOUND) endif(RTLSDR_FOUND)
if(CODEC2_FOUND)
include_directories(SYSTEM ${CODEC2_INCLUDE_DIRS})
list(APPEND LIBS ${CODEC2_LIBRARIES})
add_definitions(-DUSE_CODEC2)
endif(CODEC2_FOUND)
FILE(GLOB SRCS src/*.c src/*.cpp) FILE(GLOB SRCS src/*.c src/*.cpp)
FILE(GLOB HEADERS include/*.h include/*.hpp) FILE(GLOB HEADERS include/*.h include/*.hpp)

View File

@@ -2,9 +2,9 @@
# Digital Speech Decoder - Florida Man Edition # Digital Speech Decoder - Florida Man Edition
DSD-FME is an evolution of the original DSD project from 'DSD Author' using the base code of [szechyjs](https://github.com/szechyjs/dsd "szechyjs"), some code and ideas from [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve"), [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25") and DSD-FME is an evolution of the original DSD project from 'DSD Author' using the base code of [szechyjs](https://github.com/szechyjs/dsd "szechyjs"), some code and ideas from [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve"), [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25") and
[Osmocom OP25](https://gitea.osmocom.org/op25/op25 "Osmocom OP25"), along with other snippets of code, information, and inspirations from other projects including [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDRTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), [OK-DMRlib](https://github.com/OK-DMR/ok-dmrlib "OK-DMRlib"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"), Eric Cottrell, SP5WWP and others. Finally, this is all brought together with original code to extend the fuctionality and add new features including NCurses Terminal and Menu system, Pulse Audio, TCP Direct Link Audio, RIGCTL, Trunking Features, LRRP/GPS Mapping, P25 Phase 2, EDACS, YSF, OP25 Capture Bin compatability, etc. DSD-FME is primarily focused with Linux Desktop users in mind, so please understand that this version may not compile, compile easily, or run correctly in other environments. [Osmocom OP25](https://gitea.osmocom.org/op25/op25 "Osmocom OP25"), along with other snippets of code, information, and inspirations from other projects including [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDRTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), [OK-DMRlib](https://github.com/OK-DMR/ok-dmrlib "OK-DMRlib"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"), Eric Cottrell, SP5WWP and others. Finally, this is all brought together with original code to extend the fuctionality and add new features including NCurses Terminal and Menu system, Pulse Audio, TCP Direct Link Audio, RIGCTL, Trunking Features, LRRP/GPS Mapping, P25 Phase 2, EDACS, OP25 Capture Bin compatability, etc. DSD-FME is primarily focused with Linux Desktop users in mind, so please understand that this version may not compile, compile easily, or run correctly in other environments.
This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu, Forts, thewraithe2008, RayAir, Cretu, and others for the many hours of wav samples and information provided by them. Most importantly, HRH17, whose insight, information, samples, and willingness to let me remote into a computer half-way across the globe in order to test trunking features are what make DSD-FME what it has become. I'd also like to thank mrscanner2008 for providing an additional remote where additional NXDN Type-C, 'Idas' Type-D, and XPT decoding and trunking could be sorted out. Thank you everybody. This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu, Forts, thewraithe2008, RayAir, and others for the many hours of wav samples and information provided by them. Most importantly, HRH17, whose insight, information, samples, and willingness to let me remote into a computer half-way across the globe in order to test trunking features are what make DSD-FME what it has become. I'd also like to thank mrscanner2008 for providing an additional remote where additional NXDN Type-C, 'Idas' Type-D, and XPT decoding and trunking could be sorted out. Thank you everybody.
![DSD-FME](https://github.com/lwvmobile/dsd-fme/blob/main/dsd-fme2.png) ![DSD-FME](https://github.com/lwvmobile/dsd-fme/blob/main/dsd-fme2.png)

View File

@@ -1,31 +0,0 @@
# - Try to find CODEC2
# Once done this will define
#Seems to work on Cygwin as well now -- more testing for may be required
# Not sure what causes the 'Package 'codec2', required by 'virtual:world', not found' message, but seems to work anyways
# -- Checking for module 'codec2'
# -- Package 'codec2', required by 'virtual:world', not found
# -- Found CODEC2: /usr/local/lib/libcodec2.dll.a
if (NOT CODEC2_FOUND)
find_package(PkgConfig)
pkg_check_modules(CODEC2_PKG codec2)
set(CODEC2_DEFINITIONS ${PC_CODEC2_CFLAGS_OTHER})
find_path(CODEC2_INCLUDE_DIR
NAMES codec2/codec2.h codec2.h
HINTS ${CODEC2_PKG_INCLUDE_DIRS})
find_library(CODEC2_LIBRARY
NAMES codec2/codec2 codec2
HINTS ${CODEC2_PKG_LIBRARY_DIRS})
set(CODEC2_LIBRARIES ${CODEC2_LIBRARY})
set(CODEC2_INCLUDE_DIRS ${CODEC2_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CODEC2 DEFAULT_MSG CODEC2_LIBRARY CODEC2_INCLUDE_DIR)
mark_as_advanced(CODEC2_INCLUDE_DIR CODEC2_LIBRARY)
endif (NOT CODEC2_FOUND)

View File

@@ -13,7 +13,7 @@ Y='y'
if [[ $Y == $ANSWER ]]; then if [[ $Y == $ANSWER ]]; then
sudo apt update sudo apt update
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 libncursesw5-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 libitpp-dev libncursesw5-dev
echo ITPP Manual Build and Install has been temporarily removed from this script due to issues with older versions of Ubuntu. echo ITPP Manual Build and Install has been temporarily removed from this script due to issues with older versions of Ubuntu.
echo Please check to see that libitpp-dev has successfully been downloaded and installed from the repo. echo Please check to see that libitpp-dev has successfully been downloaded and installed from the repo.

View File

@@ -1,9 +1,9 @@
### Example Usage and Notes! ### Example Usage and Notes!
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25. To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed. `dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25 (1 and 2) . To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed.
``` ```
-ft XDMA decoder class (P25p1 and p2, YSF, and DMR Stereo) -ft XDMA decoder class (P25 1 and 2, and DMR Stereo)
-fs DMR Stereo, also may need to use -xr if inverted DMR -fs DMR Stereo, also may need to use -xr if inverted DMR
-fa Legacy Auto (not recommended) -fa Legacy Auto (not recommended)
-fi NXDN48 -fi NXDN48
@@ -12,12 +12,11 @@
-fm dPMR, also may need to use -xd if inverted dPMR. -fm dPMR, also may need to use -xd if inverted dPMR.
-fr DMR Mono, also may need to use -xr if inverted DMR. -fr DMR Mono, also may need to use -xr if inverted DMR.
-f1 P25P1 -f1 P25P1
-f2 P25P2 (may need to specify wacn/sys/nac manually) -f2 P25P2 (will need to specify wacn/sys/nac manually)
-fx X2-TDMA -fx X2-TDMA
-fy YSF
``` ```
## Conventional Frequency "Fast Scanner" ## New -- Experimental Conventional Frequency "Fast Scanner"
This feature is used to allow DSD-FME to use RIGCTL or RTL input and cycle through frequencies as fast as possible to attain a frame sync. This feature is used to allow DSD-FME to use RIGCTL or RTL input and cycle through frequencies as fast as possible to attain a frame sync.
This works almost identically to how the trunkng methods work, but instead of locking onto a control channel and tuning based on its decoding, it rapidly tunes through all loaded frequencies in a CSV file and stops when it finds a frame sync. This method is meant for loading a bunch of conventional non-trunking frequencies that signal only when voice or short data bursts are present (DMR T2, Conventional P25 P1, Conventional NXDN, etc) and decode them until the frame sync stops and then resume its scan. This method uses SDR++ RIGCTL, or RTL internal handling to go through signal. -Y is the fast scanner switch. This works almost identically to how the trunkng methods work, but instead of locking onto a control channel and tuning based on its decoding, it rapidly tunes through all loaded frequencies in a CSV file and stops when it finds a frame sync. This method is meant for loading a bunch of conventional non-trunking frequencies that signal only when voice or short data bursts are present (DMR T2, Conventional P25 P1, Conventional NXDN, etc) and decode them until the frame sync stops and then resume its scan. This method uses SDR++ RIGCTL, or RTL internal handling to go through signal. -Y is the fast scanner switch.
@@ -28,10 +27,10 @@ To scan through a mixture of DMR and P25 Conventional, use:
To scan through NXDN48 only conventional, use: To scan through NXDN48 only conventional, use:
`dsd-fme -fi -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans` `dsd-fme -fi -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans`
To scan through NXDN96 only conventional, use: To scan through NXDN98 only conventional, use:
`dsd-fme -fn -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans` `dsd-fme -fn -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans`
The Channel Map setup will be identical to any of the channel maps found for trunking systems, channel numbers do not matter and can be arbitrarily organized, and frequencies can be duplicated to be 'scanned' more frequently in larger CSV files. Scan speed by default is 1 second, and is most stable at that speed. This can be adjusted by using the `-t 2` option, for example, to specify 2 seconds of hang time per frequency. ~~If activity occurs on a frequency, an additional 2 seconds of 'hangtime' will occur on that frequency for any follow up voice activity.~~ The Channel Map setup will be identical to any of the channel maps found for trunking systems, channel numbers do not matter and can be arbitrarily organized, and frequencies can be duplicated to be 'scanned' more frequently in larger CSV files. Scan speed is purely set by your CPU/GPU, and also by other factors like using SDR++ server to connect to a SDR++ client, or RTL_TCP server to client, etc, so faster computers scan faster, and slower will scan slower, slower scans may require multiple duplicate entries into your scanner csv file if you make a really large one.
Please Note: DMR Simplex may not behave well on fast scan, I have not been able to test it as such, but given the nature of the on-off timeslot signalling on DMR Simplex, missed frame syncs and skipping/resuming scan may occur. Please Note: DMR Simplex may not behave well on fast scan, I have not been able to test it as such, but given the nature of the on-off timeslot signalling on DMR Simplex, missed frame syncs and skipping/resuming scan may occur.
@@ -64,33 +63,26 @@ Then you can open up your pavucontrol "Pulse Audio Volume Control" or "Volume Co
Wav File Input Note: Due to 96000 rate audio requiring me to double the symbol rate and center, be sure to use the -s 96000 at the very end of the startup command. Also, some NXDN48/96 may have difficulties decoding properly with wav file input. Wav File Input Note: Due to 96000 rate audio requiring me to double the symbol rate and center, be sure to use the -s 96000 at the very end of the startup command. Also, some NXDN48/96 may have difficulties decoding properly with wav file input.
## Example Usage - RTL2832 Dongle Input ## Example Usage - RTL2832 Dongle Input
Short Setup (all default values):
`dsd-fme -i rtl`
Detailed Setup:
`dsd-fme -ft -i rtl:0:154.9875M:26:-2:8:0:6020 ` `dsd-fme -ft -i rtl:0:154.9875M:26:-2:8:0:6020 `
``` ```
RTL-SDR options: RTL-SDR options:
WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>
Usage: rtl:dev:freq:gain:ppm:bw:sq:udp Usage: rtl:dev:freq:gain:ppm:bw:sq:udp
NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended
dev <num> RTL-SDR Device Index Number dev <num> RTL-SDR Device Index Number
freq <num> RTL-SDR Frequency (851800000 or 851.8M) freq <num> RTL-SDR Frequency (851800000 or 851.8M)
gain <num> RTL-SDR Device Gain (0-49)(default = 0; Hardware AGC recommended) gain <num> RTL-SDR Device Gain (0-49) (default = 26)(0 = Hardware AGC, not recommended)
ppm <num> RTL-SDR PPM Error (default = 0) ppm <num> RTL-SDR PPM Error (default = 0)
bw <num> RTL-SDR Bandwidth kHz (default = 12)(8, 12, 16, 24) bw <num> RTL-SDR VFO Bandwidth kHz (default = 12)(6, 8, 12, 24)
sq <num> RTL-SDR Squelch Level vs RMS Value (Optional) sq <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)
udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only) udp <num> RTL-SDR UDP Remote Port (default = 6020)
Example: dsd-fme-zdev -fs -i rtl -C cap_plus_channel.csv -T Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:12:0:6021
Example: dsd-fme-zdev -fp -i rtl:0:851.375M:22:-2:24:0:6021
``` ```
## Example Usage - Extra Payload/PDU Logging ## Example Usage - Extra Payload/PDU Logging
`dsd-fme -Z -N 2> log.ans` `dsd-fme -Z -N 2>> log.ans`
and in a second terminal tab, same folder, run and in a second terminal tab, same folder, run
@@ -120,11 +112,11 @@ EDACS Trunking (w/ channel map import)
`dsd-fme -i tcp -T -U 4532 -N 2> log.ans` `dsd-fme -i tcp -T -U 4532 -N 2> log.ans`
--P25 Trunking (QPSK) with P1 Control Channel (Should switch symbol rate and center on Phase 2 audio channels) --P25 Trunking (CQPSK) with P1 Control Channel (Should switch symbol rate and center on Phase 2 audio channels)
`dsd-fme -i tcp -T -U 4532 -N -mq 2> log.ans` `dsd-fme -i tcp -T -U 4532 -N -mq 2> log.ans`
--P25 Trunking Phase 2 TDMA Control Channel systems with QPSK (non Phase 1 systems) --P25 Trunking Phase 2 TDMA Control Channel systems with CQPSK (non Phase 1 systems)
`dsd-fme -i tcp -T -U 4532 -N -f2 -m2 2> log.ans` `dsd-fme -i tcp -T -U 4532 -N -f2 -m2 2> log.ans`
@@ -132,7 +124,7 @@ Trunking Note1: All samples above can also be run with the RTL input method and
`dsd-fme -fp -i rtl:0:851.8M:22:-2:24:0:6020 -T -C channel_map.csv -G group.csv -N 2> log.ans` `dsd-fme -fp -i rtl:0:851.8M:22:-2:24:0:6020 -T -C channel_map.csv -G group.csv -N 2> log.ans`
Trunking Note2: QPSK Phase 1 and Phase 2 Systems may be subceptible to LSM distortion issues, but seem to do okay, but require really good signal. Some CRC issues still occur with Phase 2 TDMA LCCH Mac Signal that can affect reliability, I believe this issue is ultimately caused by the PSK demodulation inside of FME. I also don't believe this will work on 8-level PSK, but I cannot determine that at the moment. Update: I have improved the LCCH Mac Signal decoding my increasing the QPSK decision point buffers to their maximum values. Trunking Note2: CQPSK Phase 1 and Phase 2 Systems are subceptible to LSM distortion issues, but seem to do okay, but require really good signal. Some CRC issues still occur with Phase 2 TDMA LCCH Mac Signal that can affect reliability, I believe this issue is ultimately caused by the PSK demodulation inside of FME. I also don't believe this will work on 8-level PSK, but I cannot determine that at the moment. Update: I have improved the LCCH Mac Signal decoding my increasing the QPSK decision point buffers to their maximum values.
Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have been carried out. Cap+, Con+, and TIII systems seem to do well with trunking now. Placing the frequency for the control channel at channel map 0 in your channel_map.csv file is not required now if using RIGCTL or the RTL Input, both can poll the VFO for the current frequency if it believes its on a control channel, but setting a fake channel number (i.e. 999) first with the CC frequency will result in finding the CC faster on startup if desired. If you need to map out your channels for TIII, you can observe the console output and look for channel numbers. For conveniece I have included the DSDPlus channel numbering (as best as I can figure it, but they seem consistent) into the console print so it will make it easier for users from DSDPlus to map frequencies into the channel_map.csv file. Make sure your channel numbers are the Cd (channel decimal) values from the log, and not the C+ (dsdplus) values. Notice: TIII Site ID value needs work to determine proper DMRLA values for system area and sub area. Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have been carried out. Cap+, Con+, and TIII systems seem to do well with trunking now. Placing the frequency for the control channel at channel map 0 in your channel_map.csv file is not required now if using RIGCTL or the RTL Input, both can poll the VFO for the current frequency if it believes its on a control channel, but setting a fake channel number (i.e. 999) first with the CC frequency will result in finding the CC faster on startup if desired. If you need to map out your channels for TIII, you can observe the console output and look for channel numbers. For conveniece I have included the DSDPlus channel numbering (as best as I can figure it, but they seem consistent) into the console print so it will make it easier for users from DSDPlus to map frequencies into the channel_map.csv file. Make sure your channel numbers are the Cd (channel decimal) values from the log, and not the C+ (dsdplus) values. Notice: TIII Site ID value needs work to determine proper DMRLA values for system area and sub area.
@@ -143,9 +135,9 @@ Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have be
Use channel 54 in your import file, which would correspond to dsdplus channels 109 and 110 (109 = TS0 / 110 = TS1). Use channel 54 in your import file, which would correspond to dsdplus channels 109 and 110 (109 = TS0 / 110 = TS1).
For Connect Plus, enumerate your list from 1 to the last channel and add the frequency. For Capacity Plus, LSN 1 and 2 will share the same frequency, 3 and 4 will share, 5 and 6 will share, and 7-8 will share, as Capacity Plus counts each 'channel' as two seperate channels (LSN), one for each time slot. Capacity Plus Quirk: DSD-FME makes its best effort to follow the rest channel in the event that the sync is lost for longer than the hangtime, but occassionally, DSD-FME may lose the rest channel and will have to hunt through all frequencies to find it again. For Connect Plus, enumerate your list from 1 to the last channel and add the frequency. For Capacity Plus, Rest Channels 1 and 2 will share the same frequency, 3 and 4 will share, 5 and 6 will share, and 7-8 will share, as Capacity Plus counts each 'channel' as two seperate channels (LSN), one for each time slot. Capacity Plus Quirk: DSD-FME makes its best effort to follow the rest channel in the event that the sync is lost for longer than the hangtime, but occassionally, DSD-FME will lose the rest channel and will have to hunt through all frequencies to find it again.
Trunking Note4: NXDN Trunking v1 will require a channel map. Please see the example folder for an appropriate channel map. NOTICE: NXDN trunking has been fixed on the RTL (rtl_fm) input method and works correctly now using a soft squelch value to determine when to look for frame sync. Tests show this works very well, but squelch adjustments may be required to differentiate the noise floor from the signal. Trunking Note4: NXDN Trunking v1 will require a channel map. Please see the example folder for an appropriate channel map. NOTICE: NXDN trunking will not work properly with RTL input method due to the internal handling of the RTL dongle, when using squelch, it will effectively stop all processing (including trunking/tuning) until signal is regained, but squelch is required on NXDN to prevent false sync patterns.
NXDN Trunking Update: NXDN DFA (Direct Frequency Assignment) has been coded from the v2 documents, so using a channel map may not be required, as long as the DFA is configured with standard values, and not 'system definable' values. This will only work on trunking systems that use DFA (newer systems) in accordance to the v2 CAI document NXDN TS 1-A Version 2.0 September 2016. If the system uses 'system definable' values, then make sure to put the channels in a channel map csv file as as the 16-bit OFN values for proper tuning. NXDN Trunking Update: NXDN DFA (Direct Frequency Assignment) has been coded from the v2 documents, so using a channel map may not be required, as long as the DFA is configured with standard values, and not 'system definable' values. This will only work on trunking systems that use DFA (newer systems) in accordance to the v2 CAI document NXDN TS 1-A Version 2.0 September 2016. If the system uses 'system definable' values, then make sure to put the channels in a channel map csv file as as the 16-bit OFN values for proper tuning.
@@ -153,7 +145,7 @@ NXDN Type-D/IDAS Update: Type-D or IDAS decoding/trunking has been coded now and
Channel Map and Group CSV Note: Leave the top line of the channel_map.csv and group.csv as the label, do not delete the line, if no line is there, dsd_import skips the first line so it will not import the first channel or first group in those files if there is something there that isn't a label. Channel Map and Group CSV Note: Leave the top line of the channel_map.csv and group.csv as the label, do not delete the line, if no line is there, dsd_import skips the first line so it will not import the first channel or first group in those files if there is something there that isn't a label.
Hytera XPT: Code has been added for XPT system slco/flco/csbk decoding and trunking. The setup will be similar to Capacity Plus trunking in the csv file, listing each LSN channel to a frequency (see examples/hytera_xpt_chan.csv). Currently, this set up is working with smaller XPT systems that I have been able to test with. Hytera XPT: Experimental Code has been added for XPT system slco/flco/csbk decoding and trunking. The setup will be similar to Capacity Plus trunking in the csv file, listing each LSN channel to a frequency (see examples/hytera_xpt_chan.csv). Currently, this set up is working with smaller XPT systems that I have been able to test with.
## NCurses Keyboard Shortcuts ## ## NCurses Keyboard Shortcuts ##
@@ -166,8 +158,7 @@ c - toggle compact mode
h - toggle call history h - toggle call history
z - toggle console payloads z - toggle console payloads
a - toggle call alert beep a - toggle call alert beep
4 - force privacy/scrambler key assertion over enc identifiers (dmr and nxdn) 4 - force dmr privacy key assertion over fid and svc bits
6 - force rc4 key assertion over missing pi header/le enc identifiers (dmr)
i - toggle signal inversion on types that can't auto detect (dmr, dpmr) i - toggle signal inversion on types that can't auto detect (dmr, dpmr)
m - toggle c4fm/qpsk 10/4 (everything but phase 2 signal) m - toggle c4fm/qpsk 10/4 (everything but phase 2 signal)
M - toggle c4fm/qpsk 8/3 (phase 2 tdma control channel) M - toggle c4fm/qpsk 8/3 (phase 2 tdma control channel)
@@ -175,20 +166,16 @@ R - start capturing symbol capture bin (date/time name file)
r - stop capturing symbol capture bin r - stop capturing symbol capture bin
spacebar - replay last symbol capture bin (captures must be stopped first) spacebar - replay last symbol capture bin (captures must be stopped first)
s - stop playing symbol capture bin or wav input file s - stop playing symbol capture bin or wav input file
P - start per call decoded wav files (Capital P) P - start per call decoded wav files
p - stop per call decoded wav files (Lower p) p - stop per call decoded wav files
t - toggle trunking (needs either rtl input, or rigctl connection) t - toggle trunking (needs either rtl input, or rigctl connection)
y - toggle scanner (needs either rtl input, or rigctl connection) y - toggle scanner (needs either rtl input, or rigctl connection)
1 - Lockout Tuning/Playback of TG in Slot 1 or Conventional -- Current Session Only if no group.csv file specified 1 - Lockout Tuning/Playback of TG in Slot 1 or Conventional (Current Session Only)
2 - Lockout Tuning/Playback of TG in Slot 2 -- Current Session Only if no group.csv file specified 2 - Lockout Tuning/Playback of TG in Slot 2 (Current Session Only)
0 - Toggle Audio Smoothing - May produce crackling if enabled on RTL/TCP or wav/bin files 0 - Toggle Audio Smoothing - May produce crackling if enabled on RTL/TCP or wav/bin files
w - Toggle Trunking/Playback White List (Allow A Groups Only) / Black List (Block B or DE groups only) Mode w - Toggle Trunking/Playback White List (Allow A Groups Only) / Black List (Block B or DE groups only) Mode
g - Toggle Trunking Tuning to Group Calls (DMR T3, Con+, Cap+, P25, NXDN) g - Toggle Trunking Tuning to Group Calls (DMR T3, Con+, Cap+, P25)
u - Toggle Trunking Tuning to Private Calls (DMR T3, Cap+, P25) u - Toggle Trunking Tuning to Private Calls (DMR T3, P25)
d - Toggle Trunking Tuning to Data Calls (DMR T3, NXDN) d - Toggle Trunking Tuning to Data Calls (DMR T3)
e - Toggle Trunking Tuning to Encrypted Calls (P25)
8 - Connect to SDR++ TCP Audio Sink with Defaults/Retry Sink Connection on Disconnect
9 - Connect to SDR++ RIGCTL Server with Defaults/Retry RIGCTL Connection
D - Reset DMR Site Parms/Call Strings, etc.
Z - Simulate NoCarrier/No VC/CC sync (capital Z)
``` ```

View File

@@ -2,7 +2,7 @@
### Ubuntu 22.04/20.04/LM20/Debian Bullseye or Newer: ### Ubuntu 22.04/20.04/LM20/Debian Bullseye or Newer:
Using the included download-and-install.sh should make for a simple and painless clone, build, and install on newer Debian/Ubuntu/Mint/Pi systems. Simply acquire or copy the script, and run it. Update: Ubuntu 23.04 and RPi Bullseye 64-bit has been tested working with the installer script and functions appropriately. Using the included download-and-install.sh should make for a simple and painless clone, build, and install on newer Debian/Ubuntu/Mint/Pi systems. Simply acquire or copy the script, and run it. Update: Ubuntu 22.04 and RPi Bullseye 64-bit has been tested working with the installer script and functions appropriately.
If you need all dependencies build and installed first (only on Debian/Ubuntu/Mint/Pi), run: If you need all dependencies build and installed first (only on Debian/Ubuntu/Mint/Pi), run:
@@ -11,7 +11,7 @@ wget https://raw.githubusercontent.com/lwvmobile/dsd-fme/main/download-and-insta
chmod +x download-and-install.sh chmod +x download-and-install.sh
./download-and-install.sh ./download-and-install.sh
``` ```
f
If you have dependencies already installed (i.e. need a fresh clean install on a system with DSD-FME already or using system other than Debian/Ubuntu, etc), please run this instead: If you have dependencies already installed (i.e. need a fresh clean install on a system with DSD-FME already or using system other than Debian/Ubuntu, etc), please run this instead:
``` ```
@@ -20,28 +20,23 @@ chmod +x download-and-install-nodeps.sh
./download-and-install-nodeps.sh ./download-and-install-nodeps.sh
``` ```
### Ubuntu 18.04/LM19/Buster Note:
The above install.sh should now function on older system types. You can elect to manually follow the steps down below. Do NOT Manually build and install ITPP 4.3.1 on older systems, it is currently not wanting to build on Ubuntu 18.04 and Linux Mint 19. Install it from the repository instead.
## Manual Install ## Manual Install
First, install dependency packages. This guide will assume you are using Debian/Ubuntu based distros. Check your package manager for equivalent packages if different. First, install dependency packages. This guide will assume you are using Debian/Ubuntu based distros. Check your package manager for equivalent packages if different.
Debian/Mint/Ubuntu/Pi
``` ```
sudo apt update sudo apt update
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 libncursesw5-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 libitpp-dev libncursesw5-dev
``` ```
## Headless
Fedora (Recent Releases) -- from https://github.com/lwvmobile/dsd-fme/issues/99
```
sudo dnf install libsndfile-devel fftw-devel lapack-devel rtl-sdr-devel pulseaudio-libs-devel libusb-devel cmake git ncurses ncurses-devel gcc wget pavucontrol gcc-c++ codec2-devel
```
## Headless Ubuntu Server/Pi
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. 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 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
``` ```
### Build and Install ITPP - ONLY IF NOT IN REPO!! ### Build and Install ITPP - ONLY IF NOT IN REPO!!
@@ -98,41 +93,9 @@ sudo make install
sudo ldconfig sudo ldconfig
``` ```
Optional 'Virtual Sinks' for routing audio from SDR++ or GQRX, Media Players, etc. into DSD-FME
### Windows Cygwin Builds You may wish to direct sound into DSD-FME via Virtual Sinks. You may set up a Virtual Sink or two on your machine for routing audio in and out of applications to other applications using the following command, and opening up pavucontrol "PulseAudio Volume Control" in the menu (or `pulsemixer` in headless mode) to change line out of application to virtual sink, and line in of DSD-FME to monitor of virtual sink. This command will not persist past a reboot, so you will need to invoke them each time you reboot, or search for how to add this to your conf files for persistency if desired.
If using RTL input support, you must install libusb-win32 before proceeding with Cygwin installation. You will also need to build and compile a version of librtlsdr, but this can be tricky, and personally, I had to resort to using a much older version of the source code to get it to build at all with the rtl support in the precompiled 'Aero' builds.
Then install all dependencies available in the repo prior to building, either directly selecting them during setup with the setup-x86.exe or setup-x64.exe or by issuing a command similar to this:
```
setup-x64.exe --packages libpulse-devel,libpulse-mainloop-glib0,libpulse-simple0,libpulse0,pulseaudio,pulseaudio-debuginfo,pulseaudio-equalizer,pulseaudio-module-x11,pulseaudio-module-zeroconf,pulseaudio-utils,sox-fmt-pulseaudio,xfce-pulseaudio-plugin,libusb0,libusb1.0,libusb1.0-debuginfo,libusb1.0-devel,libncurses++w10,libncurses-devel,libncursesw10,ncurses,cmake,gcc-core,gcc-debuginfo,gcc-objc,git,make,socat,sox,sox-fmt-ao,unzip,wget,gcc-g++,libsndfile-devel
```
Then manually install ITPP and MBElib, see above install notes. Be sure to run `cp libmbe* /usr/lib` after compiling MBElib.
Then you can build and install using
```
git clone https://github.com/lwvmobile/dsd-fme
cd dsd-fme
cp tone8.wav /usr/share/
cp tone24.wav /usr/share/
cp tone48.wav /usr/share/
chmod 777 /usr/share/tone8.wav
chmod 777 /usr/share/tone24.wav
chmod 777 /usr/share/tone48.wav
mkdir build
cd build
# -DAERO=ON is optional, but recommended if you want the older OSS support as well
cmake -DAERO=ON ..
make
make install
```
### Virtual Sinks
You may wish to direct sound into DSD-FME via Virtual Sinks. You may set up a Virtual Sink or two on your machine for routing audio in and out of applications to other applications using the following command, and opening up pavucontrol "PulseAudio Volume Control" in the menu (or `pulsemixer` in headless mode) to change line out of application to virtual sink, and line in of DSD-FME to monitor of virtual sink. This command will not persist past a reboot, so you will need to invoke them each time you reboot, or search for how to add this to your conf files for persistency if desired. Note: This setup is completely optional if using TCP Network Sink Audio and/or RTL Input.
``` ```
pactl load-module module-null-sink sink_name=virtual_sink sink_properties=device.description=Virtual_Sink pactl load-module module-null-sink sink_name=virtual_sink sink_properties=device.description=Virtual_Sink

View File

@@ -1,4 +1,4 @@
LSN(dec),frequency(Hz) (do not delete this line or won't import properly) ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
1,858606250 1,858606250
2,858606250 2,858606250
3,859606250 3,859606250
1 LSN(dec) ChannelNumber(dec) frequency(Hz) (do not delete this line or won't import properly)
2 1 858606250
3 2 858606250
4 3 859606250

View File

@@ -1,4 +1,4 @@
LSN(dec),frequency(Hz) (do not delete this line or won't import properly) ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
1,851375000 1,851375000
2,851800000 2,851800000
3,855987500 3,855987500
1 LSN(dec) ChannelNumber(dec) frequency(Hz) (do not delete this line or won't import properly)
2 1 1 851375000
3 2 2 851800000
4 3 3 855987500

View File

@@ -1,4 +1,4 @@
LSN(dec),frequency(Hz) (do not delete this line or won't import properly) LSN Number(dec),frequency(Hz) (do not delete this line or won't import properly)
1,858606250 1,858606250
2,858606250 2,858606250
3,859606250 3,859606250
1 LSN(dec) LSN Number(dec) frequency(Hz) (do not delete this line or won't import properly)
2 1 858606250
3 2 858606250
4 3 859606250

View File

@@ -1,4 +1,4 @@
key id or tg id (dec), key number or value (dec) //NXDN Scrambler, BP, 10-char Hytera BP only key id or tg id (dec), key number or value (dec) //NXDN, BP, 10-char Hytera BP only
2,70 2,70
1,123 1,123
100,70 100,70
1 key id or tg id (dec), key number or value (dec) //NXDN Scrambler, BP, 10-char Hytera BP only key id or tg id (dec), key number or value (dec) //NXDN, BP, 10-char Hytera BP only
2 2,70 2,70
3 1,123 1,123
4 100,70 100,70

View File

@@ -1,5 +0,0 @@
key id(hex), key value (hex) //10-char Hytera BP, RC4
1,1234567890
2,ABCDEF1234
C,0B57935150
64,0B57935150
1 key id(hex), key value (hex) //10-char Hytera BP, RC4
2 1,1234567890
3 2,ABCDEF1234
4 C,0B57935150
5 64,0B57935150

View File

@@ -1,41 +1,33 @@
#example trunking sh scripts (SDR++ with RIGCTL and RTL Input) #example trunking sh scripts (SDR++ and RTL Input) -T = trunking
#make sure to put a # in front of all lines except the one you wish to use #make sure to put a # in front of all lines except the one you wish to use
#P25 P1 FDMA CC with C4FM #P25 P1 FDMA CC with C4FM
#dsd-fme -i tcp -U 4532 -T -N 2> log.ans #dsd-fme -i tcp -U 4532 -T -N 2> log.ans
#dsd-fme -i rtl:0:850M:0:-2:12 -T -N 2> log.ans #dsd-fme -i rtl:0:850M:26:-2:8:0:6020 -T -N 2> log.ans
#P25 P1 FDMA CC with QPSK (Simulcast) #P25 P1 FDMA CC with QPSK (Simulcast)
#dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -mq -N 2> log.ans #dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -mq -N 2> log.ans
#dsd-fme -i rtl:0:855.625M:0:-2:12 -T -mq -N 2> log.ans #dsd-fme -i rtl:0:855.625M:26:-2:12:0:6020 -T -mq -N 2> log.ans
#P25 P2 TDMA CC with QPSK (Simulcast) #P25 P2 TDMA CC with QPSK (Simulcast)
#dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -f2 -m2 -N 2> log.ans #dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -f2 -m2 -N 2> log.ans
#dsd-fme -i rtl:0:855.625M:0:-2:12 -T -f2 -m2 -N 2> log.ans #dsd-fme -i rtl:0:855.625M:26:-2:12:0:6020 -T -f2 -m2 -N 2> log.ans
#P25 P2 TDMA CC with C4FM
#dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -f2 -N 2> log.ans
#dsd-fme -i rtl:0:855.625M:0:-2:12 -T -f2 -m2 -N 2> log.ans
#DMR TIII, Con+, Cap+, XPT #DMR TIII, Con+, Cap+, XPT
dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans
#dsd-fme -fs -i rtl:0:450M:44:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans #dsd-fme -fs -i rtl:0:450M:26:-2:8:0:6020 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans
#EDACS/EDACS-EA Digital Only #EDACS/EDACS-EA Digital Only
#dsd-fme -fp -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans #dsd-fme -fp -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
#dsd-fme -fp -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans #dsd-fme -fp -i rtl:0:850M:26:-2:24:0:6020 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
#NXDN48 Type-C or Type-D Trunking with Channel Map #NXDN48 Trunking with Channel Map (Custom Channels > 800)
#dsd-fme -fi -i tcp -T -U 4532 -C nxdn_channel_map.csv -N 2> log.ans #dsd-fme -fi -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans
#dsd-fme -fi -i rtl:0:855.625M:0:-2:12:100 -T -C nxdn_channel_map.csv -N 2> log.ans #NOTE! NXDN Trunking will not work correctly with the RTL input method
#NXDN48 Type-C Trunking with DFA #NXDN96 Trunking with Channel Map (Custom Channels > 800)
#dsd-fme -fi -i tcp -T -U 4532 -N 2> log.ans #dsd-fme -fn -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans
#dsd-fme -fi -i rtl:0:855.625M:0:-2:12:100 -T -N 2> log.ans #NOTE! NXDN Trunking will not work correctly with the RTL input method
#NXDN96 Trunking with Channel Map
#dsd-fme -fn -i tcp -T -U 4532 -C nxdn_channel_map.csv -N 2> log.ans
#dsd-fme -fn -i rtl -T -C nxdn_channel_map.csv -N 2> log.ans
#Notes: parameters after -i tcp can be omitted if using localhost as the default hostname to connect #Notes: parameters after -i tcp can be omitted if using localhost as the default hostname to connect
#and 7355 as the default port number. -U is the port number for RIGCTL and will mirror the tcp hostname #and 7355 as the default port number. -U is the port number for RIGCTL and will mirror the tcp hostname
@@ -44,6 +36,5 @@ dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans
#inside of SDR++ match, i.e., change in SDR++ from 'localhost' to an IP to bind to (machine's IP address) #inside of SDR++ match, i.e., change in SDR++ from 'localhost' to an IP to bind to (machine's IP address)
#Note2: RTL input should only be used on strong signal, the SDR++ VFO will perform much better on marginal signal #Note2: RTL input should only be used on strong signal, the SDR++ VFO will perform much better on marginal signal
#paramters after -i rtl can also be omitted now if using the default configurations
#Having a -G group.csv is purely optional, but useful if you want to block groups, or give groups names #Having a -G group.csv is purely optional, but useful if you want to block groups, or give groups names

View File

@@ -58,14 +58,11 @@
#include "p25p1_heuristics.h" #include "p25p1_heuristics.h"
//OSS support
#include <sys/soundcard.h>
#include <pulse/simple.h> //PULSE AUDIO #include <pulse/simple.h> //PULSE AUDIO
#include <pulse/error.h> //PULSE AUDIO #include <pulse/error.h> //PULSE AUDIO
#define SAMPLE_RATE_IN 48000 //48000 #define SAMPLE_RATE_IN 48000 //48000
#define SAMPLE_RATE_OUT 48000 //8000, #define SAMPLE_RATE_OUT 8000 //8000,
#ifdef USE_RTLSDR #ifdef USE_RTLSDR
#include <rtl-sdr.h> #include <rtl-sdr.h>
@@ -74,11 +71,7 @@
#include <locale.h> #include <locale.h>
#include <ncurses.h> #include <ncurses.h>
#ifdef USE_CODEC2 static volatile int exitflag;
#include <codec2/codec2.h>
#endif
extern volatile uint8_t exitflag; //fix for issue #136
//group csv import struct //group csv import struct
typedef struct typedef struct
@@ -208,7 +201,6 @@ typedef struct
int audio_in_type; int audio_in_type;
char audio_out_dev[1024]; char audio_out_dev[1024];
int audio_out_fd; int audio_out_fd;
int audio_out_fdR; //right channel audio for OSS hack
SNDFILE *audio_out_file; SNDFILE *audio_out_file;
SF_INFO *audio_out_file_info; SF_INFO *audio_out_file_info;
@@ -274,7 +266,6 @@ typedef struct
int rtl_udp_port; int rtl_udp_port;
int rtl_bandwidth; int rtl_bandwidth;
int rtl_started; int rtl_started;
int rtl_rms;
int monitor_input_audio; int monitor_input_audio;
int pulse_raw_rate_in; int pulse_raw_rate_in;
int pulse_raw_rate_out; int pulse_raw_rate_out;
@@ -313,9 +304,6 @@ typedef struct
int inverted_ysf; int inverted_ysf;
short int aggressive_framesync; short int aggressive_framesync;
int frame_m17;
int inverted_m17;
FILE *symbolfile; FILE *symbolfile;
int call_alert; int call_alert;
@@ -347,12 +335,12 @@ typedef struct
float trunk_hangtime; //hangtime in seconds before tuning back to CC float trunk_hangtime; //hangtime in seconds before tuning back to CC
int scanner_mode; //experimental -- use the channel map as a conventional scanner, quicker tuning, but no CC int scanner_mode; //experimental -- use the channel map as a conventional scanner, quicker tuning, but no CC
//csv import filenames //csv import filenames
char group_in_file[1024]; char group_in_file[1024];
char lcn_in_file[1024]; char lcn_in_file[1024];
char chan_in_file[1024]; char chan_in_file[1024];
char key_in_file[1024]; char key_in_file[1024];
//end import filenames //end import filenames
//reverse mute //reverse mute
@@ -365,9 +353,6 @@ typedef struct
uint8_t dmr_dmrla_is_set; //flag to tell us dmrla is set by the user uint8_t dmr_dmrla_is_set; //flag to tell us dmrla is set by the user
uint8_t dmr_dmrla_n; //n value for dmrla uint8_t dmr_dmrla_n; //n value for dmrla
//DMR Late Entry
uint8_t dmr_le; //user option to turn on or turn off late entry for enc identifiers
//Trunking - Use Group List as Allow List //Trunking - Use Group List as Allow List
uint8_t trunk_use_allow_list; uint8_t trunk_use_allow_list;
@@ -383,16 +368,10 @@ typedef struct
//Trunking - Tune Enc Calls (P25 only on applicable grants with svc opts) //Trunking - Tune Enc Calls (P25 only on applicable grants with svc opts)
uint8_t trunk_tune_enc_calls; uint8_t trunk_tune_enc_calls;
//OSS audio - slot preference
int slot_preference;
//'DSP' Format Output //'DSP' Format Output
uint8_t use_dsp_output; uint8_t use_dsp_output;
char dsp_out_file[2048]; char dsp_out_file[2048];
//Use P25p1 heuristics
uint8_t use_heuristics;
} dsd_opts; } dsd_opts;
typedef struct typedef struct
@@ -569,7 +548,7 @@ typedef struct
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte] uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
uint8_t cap_plus_csbk_bits[2][12*8*8]; //CSBK Cap+ FL initial and appended block bit storage, by slot uint8_t cap_plus_csbk_bits[2][12*8*8]; //CSBK Cap+ FL initial and appended block bit storage, by slot
uint8_t cap_plus_block_num[2]; //received block number storage -- per timeslot uint8_t cap_plus_block_num[2]; //received block number storage -- per time slot
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure) char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)
@@ -689,7 +668,7 @@ typedef struct
char nxdn_location_category[14]; char nxdn_location_category[14];
uint32_t nxdn_location_sys_code; uint32_t nxdn_location_sys_code;
uint16_t nxdn_location_site_code; uint16_t nxdn_location_site_code;
//channel access information //channel access information
uint8_t nxdn_rcn; uint8_t nxdn_rcn;
uint8_t nxdn_base_freq; uint8_t nxdn_base_freq;
@@ -704,8 +683,8 @@ typedef struct
uint64_t late_entry_mi_fragment[2][7][3]; uint64_t late_entry_mi_fragment[2][7][3];
//dmr manufacturer branding and sub_branding (i.e., Motorola and Con+) //dmr manufacturer branding and sub_branding (i.e., Motorola and Con+)
char dmr_branding[20]; char dmr_branding[99];
char dmr_branding_sub[80]; char dmr_branding_sub[99];
//Remus DMR End Call Alert Beep //Remus DMR End Call Alert Beep
int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag
@@ -713,62 +692,14 @@ typedef struct
//Upsampled Audio Smoothing //Upsampled Audio Smoothing
uint8_t audio_smoothing; uint8_t audio_smoothing;
//YSF Fusion Call Strings and Info
uint8_t ysf_dt; //data type -- VD1, VD2, Full Rate, etc.
uint8_t ysf_fi; //frame information -- HC, CC, TC
uint8_t ysf_cm; //group or private call
char ysf_tgt[11];
char ysf_src[11];
char ysf_upl[11];
char ysf_dnl[11];
char ysf_rm1[6];
char ysf_rm2[6];
char ysf_rm3[6];
char ysf_rm4[6];
char ysf_txt[21][21]; //text storage blocks
//M17 Storage
uint8_t m17_lsf[360];
uint8_t m17_str_dt; //stream contents
unsigned long long int m17_dst;
unsigned long long int m17_src;
char m17_dst_csd[20];
char m17_src_csd[20];
char m17_src_str[50];
char m17_dst_str[50];
uint8_t m17_meta[14]; //packed meta
uint8_t m17_enc; //enc type
uint8_t m17_enc_st; //scrambler or data subtye
//Codec2
#ifdef USE_CODEC2
struct CODEC2 *codec2_3200; //M17 fullrate
struct CODEC2 *codec2_1600; //M17 halfrate
#endif
} dsd_state; } dsd_state;
/* /*
* Frame sync patterns * Frame sync patterns
*/ */
//The inverse of LSF also seems to be Stream Frame Type, only going to work on Stream mode for now #define FUSION_SYNC "31111311313113131131" //HA!
#define M17_LSF "11113313" #define INV_FUSION_SYNC "13333133131331313313" //HA!
#define M17_STR "33331131"
//alternating with last symbol opposite of first symbol of LSF
#define M17_PRE "31313131"
#define M17_PIV "13131313"
#define M17_PRE_LSF "3131313133331131" //Preamble + LSF
#define M17_PIV_LSF "1313131311113313" //Preamble + LSF
// #define M17_BRT "31331111"
// #define M17_PKT "13113333"
#define FUSION_SYNC "31111311313113131131"
#define INV_FUSION_SYNC "13333133131331313313"
#define INV_P25P1_SYNC "333331331133111131311111" #define INV_P25P1_SYNC "333331331133111131311111"
#define P25P1_SYNC "111113113311333313133333" #define P25P1_SYNC "111113113311333313133333"
@@ -889,7 +820,7 @@ void openMbeOutFile (dsd_opts * opts, dsd_state * state);
void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2 void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
void openWavOutFile (dsd_opts * opts, dsd_state * state); void openWavOutFile (dsd_opts * opts, dsd_state * state);
void openWavOutFileL (dsd_opts * opts, dsd_state * state); void openWavOutFileL (dsd_opts * opts, dsd_state * state);
void openWavOutFileR (dsd_opts * opts, dsd_state * state); void openWavOutFileR (dsd_opts * opts, dsd_state * state);
void openWavOutFileRaw (dsd_opts * opts, dsd_state * state); void openWavOutFileRaw (dsd_opts * opts, dsd_state * state);
void openSymbolOutFile (dsd_opts * opts, dsd_state * state); void openSymbolOutFile (dsd_opts * opts, dsd_state * state);
void closeSymbolOutFile (dsd_opts * opts, dsd_state * state); void closeSymbolOutFile (dsd_opts * opts, dsd_state * state);
@@ -934,15 +865,12 @@ void processX2TDMAdata (dsd_opts * opts, dsd_state * state);
void processX2TDMAvoice (dsd_opts * opts, dsd_state * state); void processX2TDMAvoice (dsd_opts * opts, dsd_state * state);
void processDSTAR_HD (dsd_opts * opts, dsd_state * state); void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
void processYSF(dsd_opts * opts, dsd_state * state); //YSF void processYSF(dsd_opts * opts, dsd_state * state); //YSF
void processM17STR(dsd_opts * opts, dsd_state * state); //M17 (STR)
void processM17LSF(dsd_opts * opts, dsd_state * state); //M17 (LSF)
void processP2(dsd_opts * opts, dsd_state * state); //P2 void processP2(dsd_opts * opts, dsd_state * state); //P2
void processTSBK(dsd_opts * opts, dsd_state * state); //P25 Trunking Single Block void processTSBK(dsd_opts * opts, dsd_state * state); //P25 Trunking Single Block
void processMPDU(dsd_opts * opts, dsd_state * state); //P25 Multi Block PDU (SAP 0x61 FMT 0x15 or 0x17 for Trunking Blocks) void processMPDU(dsd_opts * opts, dsd_state * state); //P25 Multi Block PDU (SAP 0x61 FMT 0x15 or 0x17 for Trunking Blocks)
short dmr_filter(short sample); short dmr_filter(short sample);
short nxdn_filter(short sample); short nxdn_filter(short sample);
short dpmr_filter(short sample); short dpmr_filter(short sample);
short m17_filter(short sample);
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr); int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr);
uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength); uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);
@@ -962,7 +890,7 @@ void nxdn_deperm_facch2_udch (dsd_opts * opts, dsd_state * state, uint8_t bits[3
//type-d 'idas' deinterleaving/depuncturing functions //type-d 'idas' deinterleaving/depuncturing functions
void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint8_t direction); void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint8_t direction);
void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type); void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type);
//end //end
void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType); void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType);
void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]); void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]);
@@ -1029,6 +957,7 @@ uint8_t ComputeCrc5Bit(uint8_t * DMRData);
uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData); uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData);
uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData); uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData);
//new simplified dmr functions //new simplified dmr functions
void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst); void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst);
void dmr_data_sync (dsd_opts * opts, dsd_state * state); void dmr_data_sync (dsd_opts * opts, dsd_state * state);
@@ -1071,14 +1000,10 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power);
bool Hamming17123(uint8_t* d); bool Hamming17123(uint8_t* d);
uint8_t crc8(uint8_t bits[], unsigned int len); uint8_t crc8(uint8_t bits[], unsigned int len);
bool crc8_ok(uint8_t bits[], unsigned int len); bool crc8_ok(uint8_t bits[], unsigned int len);
//modified CRC functions for SB/RC
uint8_t crc7(uint8_t bits[], unsigned int len); uint8_t crc7(uint8_t bits[], unsigned int len);
uint8_t crc3(uint8_t bits[], unsigned int len);
//LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/ //LFSR code courtesy of https://github.com/mattames/LFSR/
void LFSR(dsd_state * state); void LFSR(dsd_state * state);
void LFSRP(dsd_state * state);
void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state); void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state);
void LFSR64(dsd_state * state); void LFSR64(dsd_state * state);
@@ -1120,7 +1045,6 @@ bool QR_16_7_6_decode(unsigned char *rxBits);
void InitAllFecFunction(void); void InitAllFecFunction(void);
void resetState (dsd_state * state); void resetState (dsd_state * state);
void reset_dibit_buffer(dsd_state * state);
void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]); void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]);
//P25 PDU Handler //P25 PDU Handler
@@ -1166,8 +1090,7 @@ unsigned long long int edacs_bch (unsigned long long int message);
int csvGroupImport(dsd_opts * opts, dsd_state * state); int csvGroupImport(dsd_opts * opts, dsd_state * state);
int csvLCNImport(dsd_opts * opts, dsd_state * state); int csvLCNImport(dsd_opts * opts, dsd_state * state);
int csvChanImport(dsd_opts * opts, dsd_state * state); int csvChanImport(dsd_opts * opts, dsd_state * state);
int csvKeyImportDec(dsd_opts * opts, dsd_state * state); int csvKeyImport(dsd_opts * opts, dsd_state * state);
int csvKeyImportHex(dsd_opts * opts, dsd_state * state);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -1178,9 +1101,6 @@ void open_rtlsdr_stream(dsd_opts *opts);
void cleanup_rtlsdr_stream(); void cleanup_rtlsdr_stream();
void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state); void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state);
void rtlsdr_sighandler(); void rtlsdr_sighandler();
void rtl_dev_tune(dsd_opts * opts, long int frequency);
int rtl_return_rms();
void rtl_clean_queue();
#endif #endif
//DMR TRELLIS //DMR TRELLIS
void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload); void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload);

View File

@@ -776,9 +776,9 @@ void dmr_reset_blocks (dsd_opts * opts, dsd_state * state)
memset (state->cap_plus_block_num, 0, sizeof(state->cap_plus_block_num)); memset (state->cap_plus_block_num, 0, sizeof(state->cap_plus_block_num));
memset (state->data_header_valid, 0, sizeof(state->data_header_valid)); memset (state->data_header_valid, 0, sizeof(state->data_header_valid));
memset (state->data_header_format, 7, sizeof(state->data_header_format)); memset (state->data_header_format, 7, sizeof(state->data_header_format));
//reset some strings -- resetting call string here causes random blink on ncurses terminal (cap+) //reset some strings
// sprintf (state->call_string[0], "%s", " "); //21 spaces sprintf (state->call_string[0], "%s", " "); //21 spaces
// sprintf (state->call_string[1], "%s", " "); //21 spaces sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->dmr_lrrp_gps[0], "%s", ""); sprintf (state->dmr_lrrp_gps[0], "%s", "");
sprintf (state->dmr_lrrp_gps[1], "%s", ""); sprintf (state->dmr_lrrp_gps[1], "%s", "");
} }

View File

@@ -96,10 +96,6 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//Run Loop while the getting is good //Run Loop while the getting is good
while (loop == 1) { while (loop == 1) {
memset (ambe_fr, 0, sizeof(ambe_fr));
memset (ambe_fr2, 0, sizeof(ambe_fr2));
memset (ambe_fr3, 0, sizeof(ambe_fr3));
internalslot = -1; //reset here so we know if this value is being set properly internalslot = -1; //reset here so we know if this value is being set properly
for(i = 0; i < 12; i++) for(i = 0; i < 12; i++)
{ {
@@ -118,7 +114,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//disabled for dmr_cach testing //disabled for dmr_cach testing
tact_okay = 0; tact_okay = 0;
if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1; if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1;
if (tact_okay != 1) goto END; if (tact_okay != 1) goto END; //when going to end for bad tact or emb, consider using getdibit or skipdibit to 'stash' dibits and get better return on next sync pattern? in data particularly
internalslot = state->currentslot = tact_bits[1]; internalslot = state->currentslot = tact_bits[1];
@@ -193,13 +189,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
syncdata[(2*i)+1] = (1 & dibit); // bit 0 syncdata[(2*i)+1] = (1 & dibit); // bit 0
//embedded link control //embedded link control
if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E (F for Single/RC)
{ {
state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0 state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0
} }
if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E (F for Single/RC)
{ {
state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0 state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0
@@ -267,7 +263,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr,"Sync: +DMR "); fprintf (stderr,"Sync: +DMR ");
} }
else fprintf (stderr,"Sync: -DMR "); else fprintf (stderr,"Sync: -DMR ");
vc1 = 1; vc1 = 1;
//close MBEout file - slot 1 //close MBEout file - slot 1
@@ -337,15 +333,14 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
else sprintf (polarity, "%s", "-"); else sprintf (polarity, "%s", "-");
fprintf (stderr,"Sync: %sDMR %s| Color Code=%02d | VC%d ", polarity, light, state->dmr_color_code, vc); fprintf (stderr,"Sync: %sDMR %s| Color Code=%02d | VC%d ", polarity, light, state->dmr_color_code, vc);
if (internalslot == 0 && vc1 == 6) if (internalslot == 0 && vc1 == 6)
{ {
//process embedded link control //process embedded link control
fprintf (stderr, "\n"); fprintf (stderr, "\n");
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
//check the single burst/reverse channel opportunity -- moved //check the single burst/reverse channel opportunity
// dmr_sbrc (opts, state, power); dmr_sbrc (opts, state, power);
} }
if (internalslot == 1 && vc2 == 6) if (internalslot == 1 && vc2 == 6)
@@ -353,9 +348,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//process embedded link control //process embedded link control
fprintf (stderr, "\n"); fprintf (stderr, "\n");
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
//check the single burst/reverse channel opportunity -- moved //check the single burst/reverse channel opportunity
// dmr_sbrc (opts, state, power); dmr_sbrc (opts, state, power);
} }
if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here
@@ -369,11 +363,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
processMbeFrame (opts, state, NULL, ambe_fr, NULL); processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL); processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL); processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
//run sbrc here to look for the late entry key and alg after we observe potential errors in VC6
if (internalslot == 0 && vc1 == 6) dmr_sbrc (opts, state, power);
if (internalslot == 1 && vc2 == 6) dmr_sbrc (opts, state, power);
cach_err = dmr_cach (opts, state, cachdata); cach_err = dmr_cach (opts, state, cachdata);
if (opts->payload == 0) fprintf (stderr, "\n"); if (opts->payload == 0) fprintf (stderr, "\n");
@@ -393,7 +383,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
{ {
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
state->last_cc_sync_time = time(NULL); state->last_cc_sync_time = time(NULL);
} }
//'DSP' output to file //'DSP' output to file
if (opts->use_dsp_output == 1) if (opts->use_dsp_output == 1)
@@ -413,13 +403,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (pFile, "%X", dsp_byte); fprintf (pFile, "%X", dsp_byte);
} }
fclose (pFile); fclose (pFile);
} }
//reset err checks //reset err checks
cach_err = 1; cach_err = 1;
tact_okay = 0; tact_okay = 0;
emb_ok = 0; emb_ok = 0;
//reset emb components //reset emb components
cc = 25; cc = 25;
power = 9; power = 9;
@@ -471,12 +461,12 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
//run refresh if either slot had an active MI in it. //run refresh if either slot had an active MI in it.
if (state->payload_algid >= 0x21) if (state->payload_algid != 0)
{ {
state->currentslot = 0; state->currentslot = 0;
dmr_alg_refresh (opts, state); dmr_alg_refresh (opts, state);
} }
if (state->payload_algidR >= 0x21) if (state->payload_algidR != 0)
{ {
state->currentslot = 1; state->currentslot = 1;
dmr_alg_refresh (opts, state); dmr_alg_refresh (opts, state);
@@ -498,10 +488,6 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
char ambe_fr2[4][24]; char ambe_fr2[4][24];
char ambe_fr3[4][24]; char ambe_fr3[4][24];
memset (ambe_fr, 0, sizeof(ambe_fr));
memset (ambe_fr2, 0, sizeof(ambe_fr2));
memset (ambe_fr3, 0, sizeof(ambe_fr3));
//memcpy of ambe_fr for late entry //memcpy of ambe_fr for late entry
char m1[4][24]; char m1[4][24];
char m2[4][24]; char m2[4][24];
@@ -521,7 +507,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
11, 12, 2, 13, 14, 11, 12, 2, 13, 14,
15, 3, 16, 4, 17, 18, 15, 3, 16, 4, 17, 18,
19, 5, 20, 21, 22, 6, 23 19, 5, 20, 21, 22, 6, 23
}; };
//add time to mirror printFrameSync //add time to mirror printFrameSync
time_t now; time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp char * getTime(void) //get pretty hh:mm:ss timestamp
@@ -566,7 +552,8 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
//decode and correct tact and compare //decode and correct tact and compare
if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1; if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1;
if (tact_okay != 1) goto END; if (tact_okay != 1) goto END;
internalslot = state->currentslot = tact_bits[1]; internalslot = state->currentslot = tact_bits[1];
@@ -625,7 +612,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
if ( strcmp (sync, DMR_BS_VOICE_SYNC) != 0) if ( strcmp (sync, DMR_BS_VOICE_SYNC) != 0)
{ {
sync_okay = 0; sync_okay = 0;
goto END; goto END;
} }
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
@@ -742,12 +729,12 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
//run refresh if either slot had an active MI in it. //run refresh if either slot had an active MI in it.
if (state->payload_algid >= 0x21) if (state->payload_algid != 0)
{ {
state->currentslot = 0; state->currentslot = 0;
dmr_alg_refresh (opts, state); dmr_alg_refresh (opts, state);
} }
if (state->payload_algidR >= 0x21) if (state->payload_algidR != 0)
{ {
state->currentslot = 1; state->currentslot = 1;
dmr_alg_refresh (opts, state); dmr_alg_refresh (opts, state);

View File

@@ -249,15 +249,13 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
#endif
} }
} }
@@ -686,7 +684,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
if (gi == 0) target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[40], 16); if (gi == 0) target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[40], 16);
source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[64], 16); source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[64], 16);
int rest = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[60], 4); int rest = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[60], 4);
fprintf (stderr, "Source: %d - Target: %d - Rest LSN: %d", source, target, rest); fprintf (stderr, "Source: %d - Target: %d - Rest Channel: %d", source, target, rest);
} }
else fprintf (stderr, "Source: %d - Target: %d ", source, target); else fprintf (stderr, "Source: %d - Target: %d ", source, target);
@@ -820,7 +818,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
} }
fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest LSN: %d", fl, ts, res, rest_channel); fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest Channel %d", fl, ts, res, rest_channel);
if (fl == 0) fprintf (stderr, " - Appended Block"); //have not yet observed a system use this fl value if (fl == 0) fprintf (stderr, " - Appended Block"); //have not yet observed a system use this fl value
if (fl == 1) fprintf (stderr, " - Final Block"); if (fl == 1) fprintf (stderr, " - Final Block");
if (fl == 2) fprintf (stderr, " - Initial Block"); if (fl == 2) fprintf (stderr, " - Initial Block");
@@ -854,11 +852,11 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//check for private activity on LSNs 1-8 //check for private activity on LSNs 1-8
if (fl == 1 || fl == 3) if (fl == 1 || fl == 3)
{ {
if (pdflag) //== 0x80 //testing denny's 0x80 or 0x90 flag discovery if (pdflag == 0x80)
{ {
k = 0; //= 0 k = 0; //= 0
fprintf (stderr, "\n"); fprintf (stderr, "\n");
fprintf (stderr, " Bank One F%X Private or Data Call(s) - ", pdflag); fprintf (stderr, " F%X Private or Data Call - ", pdflag);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
pch[i] = state->cap_plus_csbk_bits[ts][i+48+(group_tally*8)]; pch[i] = state->cap_plus_csbk_bits[ts][i+48+(group_tally*8)];
@@ -878,25 +876,25 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//end private/data call check on LSNs 1-8 //end private/data call check on LSNs 1-8
//check flag for appended private and/or data calls -- flag two still needs work or testing, double checking, etc, disable if issues arise //check flag for appended private and/or data calls -- flag two still needs work or testing, double checking, etc, disable if issues arise
pdflag2 = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][56+(group_tally*8)+(pd_b2*16)], 8); //48 -- had wrong value here (atleast in the one sample with the false positive) pdflag2 = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][48+(group_tally*8)+(pd_b2*16)], 8);
//check for private activity on LSNs 9-16 //check for private activity on LSNs 9-16
if (fl == 1 || fl == 3) if (fl == 1 || fl == 3)
{ {
//then check to see if this byte has a value, should be 0x80, could be other? //then check to see if this byte has a value, should be 0x80, could be other?
//this bytes location shifts depending on level of activity -- see banks above //this bytes location shifts depending on level of activity -- see banks above
if (pdflag2) //== 0x80 //testing denny's 0x80 or 0x90 flag discovery if (pdflag2 == 0x80) //now looking to see if any appended data was added
{ {
k = 0; k = 0;
fprintf (stderr, "\n"); fprintf (stderr, "\n");
fprintf (stderr, " Bank Two F%02X Private or Data Call(s) - ", pdflag2); fprintf (stderr, " F%X Private or Data Call - ", pdflag2);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
pch[i+8] = state->cap_plus_csbk_bits[ts][i+64+(group_tally*8)+(pd_b2*16)]; //56 pch[i+8] = state->cap_plus_csbk_bits[ts][i+56+(group_tally*8)+(pd_b2*16)]; //48
if (pch[i+8] == 1) if (pch[i+8] == 1)
{ {
fprintf (stderr, " LSN %02d:", i+1); fprintf (stderr, " LSN %02d:", i+1);
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][64+(k*16)+(group_tally*8)+(pd_b2*16)], 16); //56 -- had wrong value here (atleast in the one sample with the false positive) private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][64+(k*16)+(group_tally*8)+(pd_b2*16)], 16); //64
fprintf (stderr, " TGT %d;", private_target); fprintf (stderr, " TGT %d;", private_target);
k++; k++;
if (bank_two == 0) bank_two = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display if (bank_two == 0) bank_two = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display
@@ -982,7 +980,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
} }
else if (pch[i] == 1) //private or data channels else if (pch[i] == 1) //private or data channels
{ {
tg = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][(group_tally*8)+(x*16)+56], 16); //don't change this AGAIN!, this is correct! tg = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][(group_tally*8)+(x*16)+56], 16);
if (tg != 0) fprintf (stderr, "%5d; ", tg); if (tg != 0) fprintf (stderr, "%5d; ", tg);
else fprintf (stderr, " P||D; "); else fprintf (stderr, " P||D; ");
//flag as available for tuning if data calls enabled //flag as available for tuning if data calls enabled
@@ -1018,9 +1016,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//Skip tuning group calls if group calls are disabled -- moved to individual switches in the parsing phase //Skip tuning group calls if group calls are disabled -- moved to individual switches in the parsing phase
// if (opts->trunk_tune_group_calls == 0) goto SKIPCAP; // if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
//Test allowing a group in the white list to preempt a call in progress and tune to a white listed call
if (opts->trunk_use_allow_list == 1) state->last_vc_sync_time = 0;
//don't tune if vc on the current channel //don't tune if vc on the current channel
if ( (time(NULL) - state->last_vc_sync_time > 2) ) if ( (time(NULL) - state->last_vc_sync_time > 2) )
{ {
@@ -1060,16 +1055,14 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
j = 11; //break loop j = 11; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
rtl_dev_tune (opts, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1]; state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
j = 11; //break loop j = 11; //break loop
#endif
} }
} }
@@ -1205,17 +1198,15 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, state->trunk_chan_map[lcn]);
rtl_dev_tune (opts, state->trunk_chan_map[lcn]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[lcn]; state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[lcn];
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->is_con_plus = 1; //flag on state->is_con_plus = 1; //flag on
state->last_vc_sync_time = time(NULL); //bugfix: set sync here so we don't immediately tune back to CC constantly. state->last_vc_sync_time = time(NULL); //bugfix: set sync here so we don't immediately tune back to CC constantly.
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
#endif
} }
} }
@@ -1357,9 +1348,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//Skip tuning calls if group calls are disabled //Skip tuning calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPXPT; if (opts->trunk_tune_group_calls == 0) goto SKIPXPT;
//Test allowing a group in the white list to preempt a call in progress and tune to a white listed call
if (opts->trunk_use_allow_list == 1) state->last_vc_sync_time = 0;
//don't tune if vc on the current channel //don't tune if vc on the current channel
if ( (time(NULL) - state->last_vc_sync_time) > 2 ) //parenthesis error fixed if ( (time(NULL) - state->last_vc_sync_time) > 2 ) //parenthesis error fixed
{ {
@@ -1405,19 +1393,17 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
j = 11; //break loop j = 11; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR
//debug //debug
fprintf (stderr, " - Freq: %ld", state->trunk_chan_map[j+xpt_bank+1]); fprintf (stderr, " - Freq: %ld", state->trunk_chan_map[j+xpt_bank+1]);
rtl_dev_tune (opts, state->trunk_chan_map[j+xpt_bank+1]); rtl_udp_tune (opts, state, state->trunk_chan_map[j+xpt_bank+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+xpt_bank+1]; state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+xpt_bank+1];
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
j = 11; //break loop j = 11; //break loop
#endif
} }
} }

View File

@@ -75,9 +75,10 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
if ( Hamming_7_4_decode (tact_bits) ) cach_okay = 1; if ( Hamming_7_4_decode (tact_bits) ) cach_okay = 1;
else else
{ {
cach_okay = -1; cach_okay = -1;
SlotTypeOk = 0; SlotTypeOk = 0;
goto END; goto END;
} }
state->currentslot = tact_bits[1]; state->currentslot = tact_bits[1];
@@ -179,6 +180,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
dibit = (int)state->dmr_stereo_payload[65]; dibit = (int)state->dmr_stereo_payload[65];
} }
else state->dmr_stereo_payload[65] = dibit; else state->dmr_stereo_payload[65] = dibit;
SlotType[8] = (1 & (dibit >> 1)); // bit 1 SlotType[8] = (1 & (dibit >> 1)); // bit 1
SlotType[9] = (1 & dibit); // bit 0 SlotType[9] = (1 & dibit); // bit 0
@@ -253,13 +255,14 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
} }
/* Check and correct the SlotType (apply Golay(20,8) FEC check) */ /* Check and correct the SlotType (apply Golay(20,8) FEC check) */
// golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors // golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors
if( Golay_20_8_decode(SlotType) ) SlotTypeOk = 1; if( Golay_20_8_decode(SlotType) ) SlotTypeOk = 1;
else else
{ {
SlotTypeOk = 0; SlotTypeOk = 0;
goto END; goto END;
} }
state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0); state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0);
@@ -335,9 +338,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
else if (opts->audio_in_type == 3) //rtl_fm tuning else if (opts->audio_in_type == 3) //rtl_fm tuning
{ {
#ifdef USE_RTLSDR //UDP command to tune the RTL dongle
rtl_dev_tune(opts, state->p25_cc_freq); rtl_udp_tune(opts, state, state->p25_cc_freq);
#endif
} }
opts->p25_is_tuned = 0; opts->p25_is_tuned = 0;
//zero out vc frequencies //zero out vc frequencies

View File

@@ -45,13 +45,6 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
uint8_t LC_DataBytes[10]; uint8_t LC_DataBytes[10];
int Burst = -1; int Burst = -1;
memset (BPTCDeInteleavedData, 0, sizeof(BPTCDeInteleavedData));
memset (BPTCDmrDataBit, 0, sizeof(BPTCDmrDataBit));
memset (BPTCDmrDataByte, 0, sizeof(BPTCDmrDataByte));
memset (BptcDataMatrix, 0, sizeof(BptcDataMatrix));
memset (LC_DataBit, 0, sizeof(LC_DataBit));
memset (LC_DataBytes, 0, sizeof(LC_DataBytes));
//PDU Bytes and Bits //PDU Bytes and Bits
uint8_t DMR_PDU[25]; uint8_t DMR_PDU[25];
uint8_t DMR_PDU_bits[196]; uint8_t DMR_PDU_bits[196];

View File

@@ -342,7 +342,6 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
state->payload_miR = 0; state->payload_miR = 0;
state->payload_keyidR = 0; state->payload_keyidR = 0;
} }
} }
@@ -421,17 +420,22 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
if (fid == 0x10) if (fid == 0x10)
{ {
/* Check the "Service Option" bits */ /* Check the "Service Option" bits */
if(so & 0x20) if(so & 0x30)
{ {
//REMUS! Uncomment Line Below if desired /* Experimentally determined with DSD+,
// strcat (state->call_string[slot], " TXI"); * is equal to 0x2, this is a TXI call */
fprintf(stderr, "TXI "); if((so & 0x30) == 0x20)
} {
if (so & 0x10) //REMUS! Uncomment Line Below if desired
{ // strcat (state->call_string[slot], " TXI");
//REMUS! Uncomment Line Below if desired fprintf(stderr, "TXI ");
// strcat (state->call_string[slot], " RPT"); }
fprintf(stderr, "RPT "); //Short way of saying the next SF's VC6 will be pre-empted/repeat frames for the TXI backwards channel else
{
//REMUS! Uncomment Line Below if desired
// strcat (state->call_string[slot], " RES");
fprintf(stderr, "RS%d ", (so & 0x30) >> 4);
}
} }
if(so & 0x08) if(so & 0x08)
{ {
@@ -489,7 +493,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
if (restchannel != -1) if (restchannel != -1)
{ {
fprintf (stderr, "%s ", KYEL); fprintf (stderr, "%s ", KYEL);
fprintf (stderr, "Rest LSN: %d", restchannel); fprintf (stderr, "Cap+ R-Ch %d", restchannel);
} }
} }
@@ -507,65 +511,26 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
} }
} }
//BUGFIX: Include slot and algid so we don't accidentally print more than one loaded key if (state->K != 0 && fid == 0x10 && so & 0x40)
//this can happen on Missing PI header and LE when the keyloader has loaded a TG/Hash key and an RC4 key simultandeously
//subsequennt EMB would print two key values until call cleared out
if (state->K != 0 && fid == 0x10 && so & 0x40 && slot == 0 && state->payload_algid == 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %lld ", state->K);
fprintf (stderr, "%s ", KNRM);
}
if (state->K != 0 && fid == 0x10 && so & 0x40 && slot == 1 && state->payload_algidR == 0)
{ {
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %lld ", state->K); fprintf (stderr, "Key %lld ", state->K);
fprintf (stderr, "%s ", KNRM); fprintf (stderr, "%s ", KNRM);
} }
if (state->K1 != 0 && fid == 0x68 && so & 0x40 && slot == 0 && state->payload_algid == 0) if (state->K1 != 0 && fid == 0x68 && so & 0x40)
{ {
if (state->K2 != 0) fprintf (stderr, "\n "); fprintf (stderr, "\n");
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->K1); fprintf (stderr, " Key %010llX ", state->K1);
if (state->K2 != 0) fprintf (stderr, "%016llX ", state->K2); if (state->K2 != 0) fprintf (stderr, "%016llX ", state->K2);
if (state->K4 != 0) fprintf (stderr, "%016llX %016llX", state->K3, state->K4); if (state->K4 != 0) fprintf (stderr, "%016llX %016llX", state->K3, state->K4);
fprintf (stderr, "%s ", KNRM); fprintf (stderr, "%s ", KNRM);
} }
if (state->K1 != 0 && fid == 0x68 && so & 0x40 && slot == 1 && state->payload_algidR == 0)
{
if (state->K2 != 0) fprintf (stderr, "\n ");
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->K1);
if (state->K2 != 0) fprintf (stderr, "%016llX ", state->K2);
if (state->K4 != 0) fprintf (stderr, "%016llX %016llX", state->K3, state->K4);
fprintf (stderr, "%s ", KNRM);
}
if (slot == 0 && state->payload_algid == 0x21 && state->R != 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->R);
fprintf (stderr, "%s ", KNRM);
}
if (slot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->RR);
fprintf (stderr, "%s ", KNRM);
}
} }
END_FLCO: END_FLCO:
//blank the call string here if its a TLC
if (type == 2) sprintf (state->call_string[slot], "%s", " "); //21 spaces
if (unk == 1 || pf == 1) if (unk == 1 || pf == 1)
{ {
fprintf(stderr, " FLCO=0x%02X FID=0x%02X ", flco, fid); fprintf(stderr, " FLCO=0x%02X FID=0x%02X ", flco, fid);

View File

@@ -13,23 +13,6 @@ void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc,
{ {
uint8_t slot = state->currentslot; uint8_t slot = state->currentslot;
//enforce RC4 due to missing PI header, but with valid SVC Opts
//ideally, this would be handled by VC-F single burst, but its not fully reliable compared to this
//due to multiple signalling occurring inside of it, depending on system type
if (state->M == 0x21)
{
if (slot == 0 && state->dmr_so & 0x40)
{
state->payload_algid = 0x21;
state->payload_keyid = 0xFF;
}
if (slot == 1 && state->dmr_soR & 0x40)
{
state->payload_algidR = 0x21;
state->payload_keyidR = 0xFF;
}
}
//collect our fragments and place them into storage //collect our fragments and place them into storage
state->late_entry_mi_fragment[slot][vc][0] = (uint64_t)ConvertBitIntoBytes(&ambe_fr[3][0], 4); state->late_entry_mi_fragment[slot][vc][0] = (uint64_t)ConvertBitIntoBytes(&ambe_fr[3][0], 4);
@@ -178,24 +161,13 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
uint8_t slot = state->currentslot; uint8_t slot = state->currentslot;
uint8_t sbrc_interleaved[32]; uint8_t sbrc_interleaved[32];
uint8_t sbrc_return[32]; uint8_t sbrc_return[32];
uint8_t sbrc_retcrc[32]; //crc significant bits of the return for SB
memset (sbrc_interleaved, 0, sizeof(sbrc_interleaved)); memset (sbrc_interleaved, 0, sizeof(sbrc_interleaved));
memset (sbrc_return, 0, sizeof(sbrc_return)); memset (sbrc_return, 0, sizeof(sbrc_return));
memset (sbrc_retcrc, 0, sizeof(sbrc_retcrc));
uint32_t irr_err = 0; uint32_t irr_err = 0;
uint32_t sbrc_hex = 0; uint32_t sbrc_hex = 0;
uint16_t crc_extracted = 7777; uint16_t crc_extracted = 7777;
uint16_t crc_computed = 9999; uint16_t crc_computed = 9999;
uint8_t crc7_okay = 0; //RC uint8_t crc_okay = 0;
uint8_t crc3_okay = 0; //TXI
uint8_t txi = 0; //SEE: https://patents.google.com/patent/US8271009B2
//NOTE: Any previous mentions to Cap+ in this area may have been in error,
//The signalling observed here was actually TXI information, not Cap+ Specifically
//check to see if this a TXI system
if (slot == 0 && state->dmr_so & 0x20) txi = 1;
if (slot == 1 && state->dmr_soR & 0x20) txi = 1;
// 9.3.2 Pre-emption and power control Indicator (PI) // 9.3.2 Pre-emption and power control Indicator (PI)
// 0 - The embedded signalling carries information associated to the same logical channel or the Null embedded message // 0 - The embedded signalling carries information associated to the same logical channel or the Null embedded message
@@ -209,11 +181,9 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
//bad emb burst, never set a valid power indicator value (probably 9) //bad emb burst, never set a valid power indicator value (probably 9)
if (power > 1) goto SBRC_END; if (power > 1) goto SBRC_END;
//arrange the return for proper order for the crc3 check
for (i = 0; i < 8; i++) sbrc_retcrc[i] = sbrc_return[i+3];
//RC Channel CRC 7 Mask = 0x7A; CRC bits are used as privacy indicators on //RC Channel CRC 7 Mask = 0x7A; CRC bits are used as privacy indicators on
//Single Voice Burst F (see below), other moto values seem to exist there as well -- See TXI patent //Single Voice Burst F (see below), other moto values seem to exist there as well
//unknown what the other values are (see Cap+ 0x313 and 0x643)
if (power == 1) //RC if (power == 1) //RC
{ {
crc_extracted = 0; crc_extracted = 0;
@@ -223,146 +193,106 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
crc_extracted = crc_extracted | sbrc_return[i+4]; crc_extracted = crc_extracted | sbrc_return[i+4];
} }
crc_extracted = crc_extracted ^ 0x7A; crc_extracted = crc_extracted ^ 0x7A;
crc_computed = crc7((uint8_t *) sbrc_return, 7); crc_computed = crc7((uint8_t *) sbrc_return, 11);
if (crc_extracted == crc_computed) crc7_okay = 1; if (crc_extracted == crc_computed) crc_okay = 1;
} }
else //if (txi == 1) //if TXI -- but TXI systems also carry the non-crc protected ENC identifiers else crc_okay = 1; //SB
{
crc_extracted = 0;
for (i = 0; i < 3; i++)
{
crc_extracted = crc_extracted << 1;
crc_extracted = crc_extracted | sbrc_return[i]; //first 3 most significant bits
}
crc_computed = crc3((uint8_t *) sbrc_retcrc, 8); //working now seems consistent as well
if (crc_extracted == crc_computed) crc3_okay = 1;
// fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
}
// else //crc_okay = 0; //CRC invalid / not available when is ENC Identifiers (I really hate that)
for(i = 0; i < 11; i++) if (opts->payload == 1) //hide the sb/rc behind the payload printer, won't be useful to most people right now
{ {
sbrc_hex = sbrc_hex << 1; fprintf (stderr, "\n %s", KCYN);
sbrc_hex |= sbrc_return[i] & 1;
}
if (opts->payload == 1) //hide the sb/rc behind the payload printer, won't be useful to most people
{
fprintf (stderr, "%s", KCYN);
if (power == 0) fprintf (stderr, " SB: "); if (power == 0) fprintf (stderr, " SB: ");
if (power == 1) fprintf (stderr, " RC: "); if (power == 1) fprintf (stderr, " RC: ");
for(i = 0; i < 11; i++) for(i = 0; i < 11; i++)
fprintf (stderr, "%d", sbrc_return[i]);
fprintf (stderr, " - %03X; ", sbrc_hex);
fprintf (stderr, "%s", KNRM);
// if (crc_okay == 0) //forego this since the crc can vary or not be used at all
// {
// fprintf (stderr, "%s", KRED);
// fprintf (stderr, " (CRC ERR)");
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
// }
fprintf (stderr, "\n");
}
uint8_t sbrc_opcode = sbrc_hex & 0x7; //opcode and alg the same bits, but the alg is present when CRC is bad (I know they are limited on bits, but I hate that idea)
uint8_t alg = sbrc_hex & 0x7;
uint8_t key = (sbrc_hex >> 3) & 0xFF;
uint8_t txi_delay = (sbrc_hex >> 3) & 0x1F; //middle five are the 'delay' value on a TXI system
//Note: AES-256 Key 1 will pass a CRC3 due to its bit arrangement vs the CRC poly 1101
// if (irr_err == 0 && sbrc_hex = 0xD) crc3_okay = 0; //SB: 00000001101
//NOTE: on above, I belive that we need to check by opcode as well, as a CRC3 can have multiple collisions
//so we need to exclude op/alg 0 and 3 from the check (does algID 0x03/0x23 even exist?)
if (opts->dmr_le == 1) //this will now require a user to switch it on or off until more testing/figuring can be done
{
if (irr_err != 0) fprintf (stderr, "\n%s SLOT %d SB/RC (FEC ERR) %d %s \n", KRED, slot, irr_err, KNRM);
if (irr_err == 0)
{ {
if (sbrc_hex == 0) ; //NULL, do nothing sbrc_hex = sbrc_hex << 1;
sbrc_hex |= sbrc_return[i] & 1; //sbrc_return
//else if (placeholder for future conditions) fprintf (stderr, "%d", sbrc_return[i]);
// { }
// placeholder for future conditions fprintf (stderr, " - %03X", sbrc_hex);
// } fprintf (stderr, "%s", KNRM);
else if (crc7_okay == 1)
{
//do something with the reverse channel information
}
//if the call is interruptable (TXI) and the crc3 is okay and TXI Opcode
else if (crc3_okay == 1 && (sbrc_opcode == 0 || sbrc_opcode == 3) )
{
//opcodes -- 0 (NULL), BR Delay (3)
fprintf (stderr, "\n");
fprintf (stderr, " TXI Op: %X - ", sbrc_opcode);
if (sbrc_opcode == 0) fprintf (stderr, " Null; ");
else if (sbrc_opcode == 3)
{
if (txi_delay != 0)
fprintf (stderr, " BR Delay: %d - %d ms; ", txi_delay, txi_delay * 30); //could also indicate number of superframes until next VC6 pre-emption
else fprintf (stderr, "BR Delay: Irrelevant / Send at any time;");
}
else fprintf (stderr, " Unk; ");
if (opts->payload == 1) fprintf (stderr, "\n"); //only during payload
}
else if (sbrc_opcode != 0 || sbrc_opcode != 3) //all that should be left in this field is the potential ENC identifiers
{
if (slot == 0) //may not need the state->errs anymore //&& state->errs < 3
{
if (state->dmr_so & 0x40 && key != 0 && state->payload_keyid == 0)
{
//if we aren't forcing a particular alg or privacy key set
if (state->M == 0)
{
fprintf (stderr, "\n");
fprintf (stderr, "%s ", KYEL);
fprintf (stderr, " Slot 1");
fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
// fprintf (stderr, "\n");
fprintf (stderr, "%s ", KNRM);
state->payload_keyid = key;
state->payload_algid = alg + 0x20; //assuming DMRA approved alg values (moto patent)
}
}
}
if (slot == 1) //may not need the state->errs anymore //&& state->errsR < 3
{
if (state->dmr_soR & 0x40 && key != 0 && state->payload_keyidR == 0)
{
//if we aren't forcing a particular alg or privacy key set
if (state->M == 0)
{
fprintf (stderr, "\n");
fprintf (stderr, "%s ", KYEL);
fprintf (stderr, " Slot 2");
fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
// fprintf (stderr, "\n");
fprintf (stderr, "%s ", KNRM);
state->payload_keyidR = key;
state->payload_algidR = alg + 0x20; //assuming DMRA approved alg values (moto patent)
}
}
}
}
if (crc_okay == 0)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
if (opts->payload == 1) fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
} }
} }
//Disabling the lower portion until this can be completely ironed out
//sbrc_hex value of 0x313 seems to be some Cap+ Thing,
//also observed 0x643 on another cap+ system (site id, status? something?)
// uint8_t sbrc_opcode = sbrc_hex;
// uint8_t alg = sbrc_hex & 0x7;
// uint8_t key = (sbrc_hex >> 3) & 0xFF;
//this pattern seems to fit the multiple cap+ systems I've observed
//test on site '7' to make sure (works on 1 and 4)
// uint8_t cap_site = (sbrc_hex >> 4) & 0x7;
// if (opts->payload == 1)
// {
// if (irr_err != 0) fprintf (stderr, "%s (FEC ERR) %d %s", KRED, irr_err, KNRM);
// if (irr_err == 0)
// {
// if (sbrc_hex == 0) ; //NULL
// else if (strcmp (state->dmr_branding_sub, "Cap+ ") == 0)
// {
// //Cap+ Site ID seems to fit here on samples I've seen with the alternate SB signalling, but no idea what signals that info and not the emb alg/key info
// fprintf (stderr, "%s ", KYEL);
// fprintf (stderr, "\n ");
// fprintf (stderr, " Capacity Plus Site %d", cap_site);
// fprintf (stderr, "%s ", KNRM);
// }
// else
// {
// if (slot == 0)
// {
// //key and alg only present SOME times, not all,
// //also, intermixed with other signalling
// //needs more study first!
// if (state->dmr_so & 0x40 && key != 0 && state->payload_keyid == 0)
// {
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s ", KYEL);
// fprintf (stderr, "\n Slot 1");
// fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
// fprintf (stderr, "%s ", KNRM);
// }
// //needs more study before assignment
// // state->payload_keyid = key;
// // state->payload_algid = alg + 0x20; //assuming DMRA approved alg values (moto patent)
// }
// }
// if (slot == 1)
// {
// if (state->dmr_soR & 0x40 && key != 0 && state->payload_keyidR == 0)
// {
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s ", KYEL);
// fprintf (stderr, "\n Slot 2");
// fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
// fprintf (stderr, "%s ", KNRM);
// }
// //needs more study before assignment
// // state->payload_keyidR = key;
// // state->payload_algidR = alg + 0x20; //assuming DMRA approved alg values (moto patent)
// }
// }
// }
// }
// }
SBRC_END: SBRC_END:
@@ -384,27 +314,3 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
} }
uint8_t crc3(uint8_t bits[], unsigned int len)
{
uint8_t crc=0;
unsigned int K = 3;
//x^3+x+1
uint8_t poly[4] = {1,1,0,1};
uint8_t buf[256];
if (len+K > sizeof(buf)) {
return 0;
}
memset (buf, 0, sizeof(buf));
for (unsigned int i=0; i<len; i++){
buf[i] = bits[i];
}
for (unsigned int i=0; i<len; i++)
if (buf[i])
for (unsigned int j=0; j<K+1; j++)
buf[i+j] ^= poly[j];
for (unsigned int i=0; i<K; i++){
crc = (crc << 1) + buf[len + i];
}
return crc;
}

View File

@@ -87,11 +87,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
//so getDibit doesn't know to invert it before it gets here //so getDibit doesn't know to invert it before it gets here
for (j = 0; j < 6; j++) { for (j = 0; j < 6; j++) {
state->dmrburstL = 16; state->dmrburstL = 16;
memset (ambe_fr, 0, sizeof(ambe_fr));
memset (ambe_fr2, 0, sizeof(ambe_fr2));
memset (ambe_fr3, 0, sizeof(ambe_fr3));
for(i = 0; i < 12; i++) for(i = 0; i < 12; i++)
{ {
@@ -170,7 +166,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
for(i = 0; i < 24; i++) for(i = 0; i < 24; i++)
{ {
dibit = getDibit(opts, state); dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
state->dmr_stereo_payload[i+66] = dibit; state->dmr_stereo_payload[i+66] = dibit;
@@ -180,7 +176,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
sync[i] = (dibit | 1) + 48; sync[i] = (dibit | 1) + 48;
// load the superframe to do embedded signal processing // load the superframe to do embedded signal processing
if(vc > 1) //grab on vc1 values 2-5 B C D and E if(vc > 1) //grab on vc1 values 2-5 B C D and E (F for Single/RC)
{ {
state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0 state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0
@@ -216,7 +212,6 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
power = EmbeddedSignalling[4]; power = EmbeddedSignalling[4];
lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
} }
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
@@ -300,7 +295,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
processMbeFrame (opts, state, NULL, ambe_fr3, NULL); processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
} }
} }
if (vc == 6) if (vc == 6)
{ {
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
@@ -374,11 +369,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
char ambe_fr[4][24]; char ambe_fr[4][24];
char ambe_fr2[4][24]; char ambe_fr2[4][24];
char ambe_fr3[4][24]; char ambe_fr3[4][24];
char ambe_fr4[4][24]; char ambe_fr4[4][24]; //shim for crappy tdma direct, need more samples to see if this is really a necessary shim or not
memset (ambe_fr, 0, sizeof(ambe_fr));
memset (ambe_fr2, 0, sizeof(ambe_fr2));
memset (ambe_fr3, 0, sizeof(ambe_fr3));
//memcpy of ambe_fr for late entry //memcpy of ambe_fr for late entry
char m1[4][24]; char m1[4][24];

View File

@@ -26,14 +26,6 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
fprintf (stderr, "%s ", KYEL); fprintf (stderr, "%s ", KYEL);
fprintf (stderr, "\n Slot 1"); fprintf (stderr, "\n Slot 1");
fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algid, state->payload_keyid, state->payload_mi); fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algid, state->payload_keyid, state->payload_mi);
//Anytone RC4 Shim
if (state->payload_algid == 0x01)
{
fprintf (stderr, " Anytone (0x01)");
state->payload_algid = 0x21;
}
fprintf (stderr, "%s ", KNRM); fprintf (stderr, "%s ", KNRM);
if (state->payload_algid != 0x21) if (state->payload_algid != 0x21)
{ {
@@ -61,14 +53,6 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
fprintf (stderr, "%s ", KYEL); fprintf (stderr, "%s ", KYEL);
fprintf (stderr, "\n Slot 2"); fprintf (stderr, "\n Slot 2");
fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algidR, state->payload_keyidR, state->payload_miR); fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algidR, state->payload_keyidR, state->payload_miR);
//Anytone RC4 Shim
if (state->payload_algidR == 0x01)
{
fprintf (stderr, " Anytone (0x01)");
state->payload_algidR = 0x21;
}
fprintf (stderr, "%s ", KNRM); fprintf (stderr, "%s ", KNRM);
if (state->payload_algidR != 0x21) if (state->payload_algidR != 0x21)
{ {

View File

@@ -444,18 +444,17 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
if (state->audio_out_idx > opts->delay) if (state->audio_out_idx > opts->delay)
{ {
if (opts->audio_out_type == 5) //OSS // output synthesized speech to sound card
if(opts->audio_out_type == 2)
{
//go F yourself PA
}
else
{ {
//OSS //Test just sending it straight on since I think I've figured out the STDIN and RTL for Stereo
result = write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2)); pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
state->audio_out_idx = 0; state->audio_out_idx = 0;
} }
else if (opts->audio_out_type == 0)
{
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL);
state->audio_out_idx = 0;
}
else state->audio_out_idx = 0; //failsafe for audio_out == 0
} }
@@ -479,18 +478,15 @@ playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
if (state->audio_out_idxR > opts->delay) if (state->audio_out_idxR > opts->delay)
{ {
// output synthesized speech to sound card // output synthesized speech to sound card
if (opts->audio_out_type == 5) //OSS if(opts->audio_out_type == 2)
{
//go F yourself PA
}
else
{ {
//OSS pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works.
result = write (opts->audio_out_fdR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2));
state->audio_out_idxR = 0; state->audio_out_idxR = 0;
} }
else if (opts->audio_out_type == 0)
{
pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL);
state->audio_out_idxR = 0;
}
else state->audio_out_idxR = 0; //failsafe for audio_out == 0
} }
@@ -547,7 +543,7 @@ openAudioInDevice (dsd_opts * opts)
//if no extension set, give default of .wav -- bugfix for github issue #105 //if no extension set, give default of .wav -- bugfix for github issue #105
// if (extension == NULL) extension = ".wav"; // if (extension == NULL) extension = ".wav";
// get info of device/file // get info of device/file
if (strncmp(opts->audio_in_dev, "-", 1) == 0) if (strncmp(opts->audio_in_dev, "-", 1) == 0)
{ {
@@ -565,7 +561,6 @@ openAudioInDevice (dsd_opts * opts)
exit(1); exit(1);
} }
} }
else if (strncmp(opts->audio_in_dev, "tcp", 3) == 0) else if (strncmp(opts->audio_in_dev, "tcp", 3) == 0)
{ {
opts->audio_in_type = 8; opts->audio_in_type = 8;
@@ -575,13 +570,13 @@ openAudioInDevice (dsd_opts * opts)
opts->audio_in_file_info->seekable=0; opts->audio_in_file_info->seekable=0;
opts->audio_in_file_info->format=SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE; opts->audio_in_file_info->format=SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE;
opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0); opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
if(opts->tcp_file_in == NULL) if(opts->tcp_file_in == NULL)
{ {
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL)); fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
exit(1); exit(1);
} }
} }
else if (strncmp(opts->audio_in_dev, "udp", 3) == 0) else if (strncmp(opts->audio_in_dev, "udp", 3) == 0)
{ {
opts->audio_in_type = 6; opts->audio_in_type = 6;
@@ -600,24 +595,12 @@ openAudioInDevice (dsd_opts * opts)
} }
else if(strncmp(opts->audio_in_dev, "rtl", 3) == 0) else if(strncmp(opts->audio_in_dev, "rtl", 3) == 0)
{ {
#ifdef USE_RTLSDR
opts->audio_in_type = 3; opts->audio_in_type = 3;
#elif AERO_BUILD
opts->audio_in_type = 5;
sprintf (opts->audio_in_dev, "/dev/dsp");
#else
opts->audio_in_type = 0;
sprintf (opts->audio_in_dev, "pulse");
#endif
} }
else if(strncmp(opts->audio_in_dev, "pulse", 5) == 0) else if(strncmp(opts->audio_in_dev, "pulse", 5) == 0)
{ {
opts->audio_in_type = 0; opts->audio_in_type = 0;
} }
else if((strncmp(opts->audio_in_dev, "/dev/dsp", 8) == 0))
{
opts->audio_in_type = 5;
}
//if no extension set, treat as named pipe or extensionless wav file -- bugfix for github issue #105 //if no extension set, treat as named pipe or extensionless wav file -- bugfix for github issue #105
else if (extension == NULL) else if (extension == NULL)
@@ -637,47 +620,6 @@ openAudioInDevice (dsd_opts * opts)
} }
} }
//test .rrc files with hardset wav file settings
else if (strncmp(extension, ".rrc", 3) == 0)
{
//debug
fprintf (stderr, "Opening M17 .rrc headless wav file\n");
opts->audio_in_type = 2;
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->samplerate = 48000;
opts->audio_in_file_info->channels = 1;
opts->audio_in_file_info->seekable = 0;
opts->audio_in_file_info->format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
if(opts->audio_in_file == NULL)
{
fprintf(stderr, "Error, couldn't open %s with libsndfile: %s\n", opts->audio_in_dev, sf_strerror(NULL));
exit(1);
}
}
//TODO: test .sym files as symbol capture .bin files
else if (strncmp(extension, ".sym", 3) == 0)
{
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0)
{
fprintf (stderr,"Error, couldn't open bin file %s\n", opts->audio_in_dev);
exit(1);
}
if (S_ISREG(stat_buf.st_mode))
{
opts->symbolfile = fopen(opts->audio_in_dev, "r");
opts->audio_in_type = 4; //symbol capture bin files
}
else
{
opts->audio_in_type = 0;
}
}
else if (strncmp(extension, ".bin", 3) == 0) else if (strncmp(extension, ".bin", 3) == 0)
{ {
struct stat stat_buf; struct stat stat_buf;
@@ -725,11 +667,9 @@ openAudioInDevice (dsd_opts * opts)
} }
//open pulse audio if no bin or wav //open pulse audio if no bin or wav
else //seems this condition is never met else
{ {
//opts->audio_in_type = 5; //not sure if this works or needs to openPulse here opts->audio_in_type = 0; //not sure if this works or needs to openPulse here
fprintf(stderr, "Error, couldn't open input file.\n");
exit(1);
} }
} }
if (opts->split == 1) if (opts->split == 1)

View File

@@ -265,33 +265,30 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) || else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) ||
(state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) || (state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) ||
(state->synctype == 17) || (state->synctype == 29) || (state->synctype == 31) || (state->synctype == 17) || (state->synctype == 29) || (state->synctype == 36) )
(state->synctype == 36) || (state->synctype == 99) )
{ {
// 1 -P25p1 // 1 -P25p1
// 3 -X2-TDMA (inverted signal voice frame) // 3 -X2-TDMA (inverted signal voice frame)
// 5 -X2-TDMA (inverted signal data frame) // 5 -X2-TDMA (inverted signal data frame)
// 9 -M17 LSR // 9 -NXDN (inverted voice frame)
// 11 -DMR (inverted signal voice frame) // 11 -DMR (inverted signal voice frame)
// 13 -DMR (inverted signal data frame) // 13 -DMR (inverted signal data frame)
// 17 -M17 STR // 17 -NXDN (inverted data frame)
// 29 -NXDN (inverted FSW) // 29 -NXDN (inverted FSW)
// 31 -YSF
// 36 -P25p2 // 36 -P25p2
// 99 -M17 Preamble
int valid; int valid;
int dibit; int dibit;
valid = 0; valid = 0;
//testing again, either on Voice channels only (when tuned) or with trunk disabled //disabling again, causing issues with trunking
if (state->synctype == 1 && (opts->p25_is_tuned == 1 || opts->p25_trunk == 0) && opts->use_heuristics == 1) if (state->synctype == 1 && opts->p25_trunk == 1)
{ {
// Use the P25p1 heuristics if available // Use the P25 heuristics if available
valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit); // valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit);
} }
if (valid == 0) if (valid == 0)
{ {
@@ -338,26 +335,24 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
// 0 +P25p1 // 0 +P25p1
// 2 +X2-TDMA (non inverted signal data frame) // 2 +X2-TDMA (non inverted signal data frame)
// 4 +X2-TDMA (non inverted signal voice frame) // 4 +X2-TDMA (non inverted signal voice frame)
// 8 +M17 LSF // 8 +NXDN (non inverted voice frame)
// 10 +DMR (non inverted signal data frame) // 10 +DMR (non inverted signal data frame)
// 12 +DMR (non inverted signal voice frame) // 12 +DMR (non inverted signal voice frame)
// 16 +M17 STR // 16 +NXDN (non inverted data frame)
// 28 +NXND (FSW) // 28 +NXND (FSW)
// 30 +YSF
// 35 +p25p2 // 35 +p25p2
// 98 +M17 Preamble
int valid; int valid;
int dibit; int dibit;
valid = 0; valid = 0;
//testing again, either on Voice channels only (when tuned) or with trunk disabled //disabling again, causing issues with trunking
if (state->synctype == 0 && (opts->p25_is_tuned == 1 || opts->p25_trunk == 0) && opts->use_heuristics == 1) if (state->synctype == 0 && opts->p25_trunk == 1)
{ {
// Use the P25p1 heuristics if available // Use the P25 heuristics if available
valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit); // valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit);
} }
if (valid == 0) if (valid == 0)
{ {

View File

@@ -34,7 +34,7 @@ char * getTimeF(void) //get pretty hh:mm:ss timestamp
} }
char * getDateF(void) { char * getDateF(void) {
char datename[80]; //32-bit needs this to be 80 char datename[120]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char * curr2; char * curr2;
struct tm * to; struct tm * to;
time_t t; time_t t;

View File

@@ -1,36 +1,8 @@
//M17 Filter -- RRC Alpha = 0.5 S/s 48000 with 81 taps
#define M17ZEROS 80 //ONLY SEE 79 THOUGH
float m17gain = 10.0f;
static float m17xv[M17ZEROS+1];
float m17coeffs[81] =
{
-0.009265784007800534, -0.006136551625729697, -0.001125978562075172, 0.004891777252042491,
0.01071805138282269, 0.01505751553351295, 0.01679337935001369, 0.015256245142156299,
0.01042830577908502, 0.003031522725559901, -0.0055333532968188165, -0.013403099825723372,
-0.018598682349642525, -0.01944761739590459, -0.015005271935951746, -0.0053887880354343935,
0.008056525910253532, 0.022816244158307273, 0.035513467692208076, 0.04244131815783876,
0.04025481153629372, 0.02671818654865632, 0.0013810216516704976, -0.03394615682795165,
-0.07502635967975885, -0.11540977897637611, -0.14703962203941534, -0.16119995609538576,
-0.14969512896336504, -0.10610329539459686, -0.026921412469634916, 0.08757875030779196,
0.23293327870303457, 0.4006012210123992, 0.5786324696325503, 0.7528286479934068,
0.908262741447522, 1.0309661131633199, 1.1095611856548013, 1.1366197723675815,
1.1095611856548013, 1.0309661131633199, 0.908262741447522, 0.7528286479934068,
0.5786324696325503, 0.4006012210123992, 0.23293327870303457, 0.08757875030779196,
-0.026921412469634916, -0.10610329539459686, -0.14969512896336504, -0.16119995609538576,
-0.14703962203941534, -0.11540977897637611, -0.07502635967975885, -0.03394615682795165,
0.0013810216516704976, 0.02671818654865632, 0.04025481153629372, 0.04244131815783876,
0.035513467692208076, 0.022816244158307273, 0.008056525910253532, -0.0053887880354343935,
-0.015005271935951746, -0.01944761739590459, -0.018598682349642525, -0.013403099825723372,
-0.0055333532968188165, 0.003031522725559901, 0.01042830577908502, 0.015256245142156299,
0.01679337935001369, 0.01505751553351295, 0.01071805138282269, 0.004891777252042491,
-0.001125978562075172, -0.006136551625729697, -0.009265784007800534
};
// Original DMR filter // Original DMR filter
#define NZEROS 60 #define NZEROS 60
float ngain = 7.423339364f; float ngain = 7.423339364f;
static float xv[NZEROS+1]; static float xv[NZEROS+1];
float xcoeffs[61] = float xcoeffs[] =
{ -0.0083649323f, -0.0265444850f, -0.0428141462f, -0.0537571943f, { -0.0083649323f, -0.0265444850f, -0.0428141462f, -0.0537571943f,
-0.0564141052f, -0.0489161045f, -0.0310068662f, -0.0043393881f, -0.0564141052f, -0.0489161045f, -0.0310068662f, -0.0043393881f,
+0.0275375106f, +0.0595423283f, +0.0857543325f, +0.1003565948f, +0.0275375106f, +0.0595423283f, +0.0857543325f, +0.1003565948f,
@@ -55,7 +27,7 @@ float xcoeffs[61] =
float nxgain = 15.95930463f; float nxgain = 15.95930463f;
static float nxv[NXZEROS+1]; static float nxv[NXZEROS+1];
float nxcoeffs[135] = float nxcoeffs[] =
{ +0.031462429f, +0.031747267f, +0.030401148f, +0.027362877f, { +0.031462429f, +0.031747267f, +0.030401148f, +0.027362877f,
+0.022653298f, +0.016379869f, +0.008737200f, +0.000003302f, +0.022653298f, +0.016379869f, +0.008737200f, +0.000003302f,
-0.009468531f, -0.019262057f, -0.028914291f, -0.037935027f, -0.009468531f, -0.019262057f, -0.028914291f, -0.037935027f,
@@ -102,7 +74,7 @@ const float dmrgain = 6.82973073748f;
static float dxv[DMRNZEROS+1]; static float dxv[DMRNZEROS+1];
// DMR filter F4EXB - root raised cosine alpha=0.7 Ts = 6650 S/s Fc = 48kHz // DMR filter F4EXB - root raised cosine alpha=0.7 Ts = 6650 S/s Fc = 48kHz
const float dmrcoeffs[61] = const float dmrcoeffs[] =
{0.0301506278, 0.0269200615, 0.0159662432, -0.0013114705, -0.0216605133, {0.0301506278, 0.0269200615, 0.0159662432, -0.0013114705, -0.0216605133,
-0.0404938748, -0.0528141756, -0.0543747957, -0.0428325003, -0.0186176083, -0.0404938748, -0.0528141756, -0.0543747957, -0.0428325003, -0.0186176083,
0.0147202645, 0.0508418571, 0.0816392577, 0.0988113688, 0.0957187780, 0.0147202645, 0.0508418571, 0.0816392577, 0.0988113688, 0.0957187780,
@@ -126,7 +98,7 @@ static float dpmrxv[NXZEROS+1];
const float dpmrgain = 14.6083498224f; const float dpmrgain = 14.6083498224f;
// dPMR filter - root raised cosine alpha=0.2 Ts = 3325 S/s Fc = 48 kHz - zero at boundaries appears to be slightly better // dPMR filter - root raised cosine alpha=0.2 Ts = 3325 S/s Fc = 48 kHz - zero at boundaries appears to be slightly better
const float dpmrcoeffs[135] = const float dpmrcoeffs[] =
{-0.0000983004, 0.0058388841, 0.0119748846, 0.0179185547, 0.0232592816, {-0.0000983004, 0.0058388841, 0.0119748846, 0.0179185547, 0.0232592816,
0.0275919612, 0.0305433586, 0.0317982965, 0.0311240307, 0.0275919612, 0.0305433586, 0.0317982965, 0.0311240307,
0.0283911865, 0.0235897433, 0.0168387650, 0.0083888763, 0.0283911865, 0.0235897433, 0.0168387650, 0.0083888763,
@@ -184,11 +156,6 @@ dpmr_filter(short sample)
return dsd_input_filter(sample, 4); return dsd_input_filter(sample, 4);
} }
short m17_filter (short sample)
{
return dsd_input_filter(sample, 5);
}
short short
dsd_input_filter(short sample, int mode) dsd_input_filter(short sample, int mode)
@@ -222,14 +189,6 @@ dsd_input_filter(short sample, int mode)
coeffs = (float *)dpmrcoeffs; coeffs = (float *)dpmrcoeffs;
zeros = DPMRNZEROS; zeros = DPMRNZEROS;
break; break;
case 5:
gain = m17gain;
v = m17xv;
coeffs = (float *)m17coeffs;
zeros = M17ZEROS;
break;
default: default:
return sample; return sample;
} }

View File

@@ -290,21 +290,16 @@ processFrame (dsd_opts * opts, dsd_state * state)
//ysf //ysf
else if ((state->synctype == 30) || (state->synctype == 31)) else if ((state->synctype == 30) || (state->synctype == 31))
{ {
//relocate MBEout to inside frame handling -- Not Working Currently for YSF //Do stuff
//fprintf(stderr, "YSF Sync! \n");
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
//openMbeOutFile (opts, state);
}
//sprintf(state->fsubtype, " VOICE ");
processYSF(opts, state); processYSF(opts, state);
return; return;
} }
//M17
else if ((state->synctype == 16) || (state->synctype == 9) || (state->synctype == 17) || (state->synctype == 8) || (state->synctype == 99) || (state->synctype == 98))
{
if (state->synctype == 98 || state->synctype == 99) //preamble only
skipDibit(opts, state, 184); //skip dibits to prime the demodulator
else if (state->synctype == 16 || state->synctype == 17)
processM17STR(opts, state);
else
processM17LSF(opts, state);
return;
}
//P25 P2 //P25 P2
else if ((state->synctype == 35) || (state->synctype == 36)) else if ((state->synctype == 35) || (state->synctype == 36))
{ {

View File

@@ -114,16 +114,16 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
* 5 = -X2-TDMA (inverted signal data frame) * 5 = -X2-TDMA (inverted signal data frame)
* 6 = +D-STAR * 6 = +D-STAR
* 7 = -D-STAR * 7 = -D-STAR
* 8 = +M17 STR (non inverted stream frame) * 8 = +NXDN (non inverted voice frame)
* 9 = -M17 STR (inverted stream frame) * 9 = -NXDN (inverted voice frame)
* 10 = +DMR (non inverted signal data frame) * 10 = +DMR (non inverted signal data frame)
* 11 = -DMR (inverted signal voice frame) * 11 = -DMR (inverted signal voice frame)
* 12 = +DMR (non inverted signal voice frame) * 12 = +DMR (non inverted signal voice frame)
* 13 = -DMR (inverted signal data frame) * 13 = -DMR (inverted signal data frame)
* 14 = +ProVoice * 14 = +ProVoice
* 15 = -ProVoice * 15 = -ProVoice
* 16 = +M17 LSF (non inverted link frame) * 16 = +NXDN (non inverted data frame)
* 17 = -M17 LSF (inverted link frame) * 17 = -NXDN (inverted data frame)
* 18 = +D-STAR_HD * 18 = +D-STAR_HD
* 19 = -D-STAR_HD * 19 = -D-STAR_HD
* 20 = +dPMR Frame Sync 1 * 20 = +dPMR Frame Sync 1
@@ -189,12 +189,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[state->lcn_freq_roll]); SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[state->lcn_freq_roll]);
} }
//rtl //rtludp
if (opts->audio_in_type == 3) if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, state->trunk_lcn_freq[state->lcn_freq_roll]);
rtl_dev_tune (opts, state->trunk_lcn_freq[state->lcn_freq_roll]);
#endif
} }
fprintf (stderr, "Tuning to Frequency: %.06lf MHz\n", fprintf (stderr, "Tuning to Frequency: %.06lf MHz\n",
@@ -215,8 +213,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
char synctest20[21]; //YSF char synctest20[21]; //YSF
char synctest21[22]; //P25 S-OEMI (SACCH) char synctest21[22]; //P25 S-OEMI (SACCH)
char synctest48[49]; //EDACS char synctest48[49]; //EDACS
char synctest8[9]; //M17
char synctest16[17]; //M17 Preamble
char modulation[8]; char modulation[8];
char *synctest_p; char *synctest_p;
int symboltest_pos; //symbol test position, match to synctest_pos int symboltest_pos; //symbol test position, match to synctest_pos
@@ -230,21 +226,13 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{ {
t_max = 10; t_max = 10;
} }
//dPMR //else if dPMR
else if (opts->frame_dpmr == 1) else if (opts->frame_dpmr == 1)
{ {
t_max = 12; //based on Frame_Sync_2 pattern t_max = 12; //based on Frame_Sync_2 pattern
} }
else if (opts->frame_m17 == 1) //if Phase 2 (or YSF in future), then only 19
{ else if (state->lastsynctype == 35 || state->lastsynctype == 36) //P2
t_max = 8;
}
else if (state->lastsynctype == 30 || state->lastsynctype == 31 )
{
t_max = 20; //20 on YSF
}
//if Phase 2, then only 19
else if (state->lastsynctype == 35 || state->lastsynctype == 36 )
{ {
t_max = 19; //Phase 2 S-ISCH is only 19 t_max = 19; //Phase 2 S-ISCH is only 19
} }
@@ -458,16 +446,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->minref = state->min; state->minref = state->min;
} }
//if using an rtl input method, do not look for sync patterns if the rms value is lower than our 'soft squelch' level
if (opts->audio_in_type == 3 && opts->rtl_rms < opts->rtl_squelch_level)
{
if (opts->frame_nxdn48 == 1 || opts->frame_nxdn96 == 1 || opts->frame_dpmr == 1 || opts->frame_m17 == 1)
{
goto SYNC_TEST_END;
}
}
strncpy (synctest, (synctest_p - 23), 24); strncpy (synctest, (synctest_p - 23), 24);
if (opts->frame_p25p1 == 1) if (opts->frame_p25p1 == 1)
{ {
@@ -578,138 +556,51 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} }
} }
//YSF sync //YSF sync
strncpy(synctest20, (synctest_p - 19), 20); strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right
if(opts->frame_ysf == 1) if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
{ {
if (strcmp(synctest20, FUSION_SYNC) == 0) if (0 == 0) //opts->inverted_ysf == 0
{ {
printFrameSync (opts, state, "+YSF ", synctest_pos + 1, modulation); if (strcmp(synctest20, FUSION_SYNC) == 0)
state->carrier = 1; {
state->offset = synctest_pos; state->carrier = 1;
state->max = ((state->max) + lmax) / 2; state->offset = synctest_pos;
state->min = ((state->min) + lmin) / 2; state->max = ((state->max) + lmax) / 2;
opts->inverted_ysf = 0; state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 30; fprintf (stderr, "\nYSF FUSION SYNC \n");
return (30); opts->inverted_ysf = 0; //should we set this here?
state->lastsynctype = 30;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (30);
}
} }
else if (strcmp(synctest20, INV_FUSION_SYNC) == 0) }
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
{
if (0 == 0) //opts->inverted_ysf == 1
{ {
printFrameSync (opts, state, "-YSF ", synctest_pos + 1, modulation); if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
state->carrier = 1; {
state->offset = synctest_pos; state->carrier = 1;
state->max = ((state->max) + lmax) / 2; state->offset = synctest_pos;
state->min = ((state->min) + lmin) / 2; state->max = ((state->max) + lmax) / 2;
opts->inverted_ysf = 1; state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 31; fprintf (stderr, "\nINVERTED YSF FUSION SYNC \n");
return (31); opts->inverted_ysf = 1; //should we set this here?
state->lastsynctype = 31;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (31);
}
} }
} }
//end YSF sync //end YSF sync
//M17 Sync -- Just STR and LSF for now
strncpy(synctest16, (synctest_p - 15), 16);
strncpy(synctest8, (synctest_p - 7), 8);
if(opts->frame_m17 == 1)
{
//preambles will skip dibits in an attempt to prime the
//demodulator but not attempt any decoding
if (strcmp(synctest8, M17_PRE) == 0)
{
if (opts->inverted_m17 == 0)
{
printFrameSync (opts, state, "+M17 PREAMBLE", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 98;
fprintf (stderr, "\n");
return (98);
}
}
else if (strcmp(synctest8, M17_PIV) == 0)
{
if (opts->inverted_m17 == 1)
{
printFrameSync (opts, state, "-M17 PREAMBLE", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 99;
fprintf (stderr, "\n");
return (99);
}
}
else if (strcmp(synctest8, M17_STR) == 0)
{
if (opts->inverted_m17 == 0)
{
printFrameSync (opts, state, "+M17 STR", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 16 || state->lastsynctype == 8)
{
state->lastsynctype = 16;
return (16);
}
state->lastsynctype = 16;
fprintf (stderr, "\n");
}
else
{
printFrameSync (opts, state, "-M17 LSF", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 99)
{
state->lastsynctype = 9;
return (9);
}
state->lastsynctype = 9;
fprintf (stderr, "\n");
}
}
else if (strcmp(synctest8, M17_LSF) == 0)
{
if (opts->inverted_m17 == 1)
{
printFrameSync (opts, state, "-M17 STR", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 17 || state->lastsynctype == 9)
{
state->lastsynctype = 17;
return (17);
}
state->lastsynctype = 17;
fprintf (stderr, "\n");
}
else
{
printFrameSync (opts, state, "+M17 LSF", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 98)
{
state->lastsynctype = 8;
return (8);
}
state->lastsynctype = 8;
fprintf (stderr, "\n");
}
}
}
//end M17
//P25 P2 sync S-ISCH VCH //P25 P2 sync S-ISCH VCH
strncpy(synctest20, (synctest_p - 19), 20); strncpy(synctest20, (synctest_p - 19), 20);
if(opts->frame_p25p2 == 1) if(opts->frame_p25p2 == 1)
@@ -1386,7 +1277,120 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} }
#ifdef NXDNOLDSYNC //Use FSW vs strncmperr method #ifdef NXDNTESTSYNC //use experimental sync detection based on multiple factors
//NXDN FSW sync and handling - testing with more exact syncs patterns
else if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
{
strncpy (synctest10, (synctest_p - 9), 10); //FSW only
strncpy (synctest19, (synctest_p - 18), 19); //Preamble + FSW
//Using Hard Coded Sync Strings with variations for the areas where the symbol
//error will occur due to the demodulation issues internally
//Preamble plus FSW, proceed right away
if (
(strcmp (synctest19, "3131133313131331131") == 0 )
|| (strcmp (synctest19, "3131133313331331131") == 0 )
|| (strcmp (synctest19, "3131133313131331111") == 0 )
|| (strcmp (synctest19, "3131133313331331111") == 0 )
)
{
// state->carrier = 1;
state->lastsynctype = 28;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
// if (opts->payload == 1)
// fprintf (stderr, "\n +PANDF ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest19);
return (28);
}
else if (
(strcmp (synctest19, "1313311133131331131") == 0 )
|| (strcmp (synctest19, "1313311133331331131") == 0 )
|| (strcmp (synctest19, "1313311133131331111") == 0 )
|| (strcmp (synctest19, "1313311133331331111") == 0 )
)
{
// state->carrier = 1;
state->lastsynctype = 29;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
// if (opts->payload == 1)
// fprintf (stderr, "\n -PANDF ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest19);
return (29);
}
else if (
(strcmp (synctest10, "3131331131") == 0 )
|| (strcmp (synctest10, "3331331131") == 0 )
|| (strcmp (synctest10, "3131331111") == 0 )
|| (strcmp (synctest10, "3331331111") == 0 )
)
{
// state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 28)
{
state->lastsynctype = 28;
// if (opts->payload == 1)
// fprintf (stderr, "\n +FSW ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest10);
return (28);
}
state->lastsynctype = 28;
}
else if (
(strcmp (synctest10, "1313113313") == 0 )
|| (strcmp (synctest10, "1113113313") == 0 )
|| (strcmp (synctest10, "1313113333") == 0 )
|| (strcmp (synctest10, "1113113333") == 0 )
)
{
// state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 29)
{
state->lastsynctype = 29;
// if (opts->payload == 1)
// fprintf (stderr, "\n -FSW ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest10);
return (29);
}
state->lastsynctype = 29;
}
}
#else //use current 'more stable' NXDN Sync pattern detection
//NXDN FSW sync and handling - moved to very bottom of sync stack for falsing sanity //NXDN FSW sync and handling - moved to very bottom of sync stack for falsing sanity
else if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1)) else if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
@@ -1397,7 +1401,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//Preamble plus FSW, proceed right away //Preamble plus FSW, proceed right away
if ( (strncmperr (synctest19, NXDN_PANDFSW, 19, 1) == 0) ) if ( (strncmperr (synctest19, NXDN_PANDFSW, 19, 1) == 0) )
{ {
state->carrier = 1; // state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
@@ -1410,7 +1414,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest19, INV_NXDN_PANDFSW, 19, 1) == 0) ) else if ( (strncmperr (synctest19, INV_NXDN_PANDFSW, 19, 1) == 0) )
{ {
state->carrier = 1; // state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
@@ -1423,7 +1427,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest10, NXDN_FSW, 10, 1) == 0) ) else if ( (strncmperr (synctest10, NXDN_FSW, 10, 1) == 0) )
{ {
state->carrier = 1; // state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
@@ -1441,7 +1445,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest10, INV_NXDN_FSW, 10, 1) == 0) ) else if ( (strncmperr (synctest10, INV_NXDN_FSW, 10, 1) == 0) )
{ {
state->carrier = 1; // state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
@@ -1458,125 +1462,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} }
} }
#else //use Current FSW Pattern
//NXDN FSW sync and handling - using more exact frame sync values
else if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
{
strncpy (synctest10, (synctest_p - 9), 10); //FSW only
strncpy (synctest19, (synctest_p - 18), 19); //Preamble + FSW
//Using Hard Coded Sync Strings with variations for the areas where the symbol
//error will occur due to the demodulation issues internally
//Disabling the Preamble+FSW version for now
//its nearly impossible to catch it
//Preamble plus FSW, proceed right away
// if (
// (strcmp (synctest19, "3131133313131331131") == 0 )
// || (strcmp (synctest19, "3131133313331331131") == 0 )
// || (strcmp (synctest19, "3131133313131331111") == 0 )
// || (strcmp (synctest19, "3131133313331331111") == 0 )
// )
// {
// //state->carrier = 1;
// state->offset = synctest_pos;
// state->max = ((state->max) + lmax) / 2;
// state->min = ((state->min) + lmin) / 2;
// state->lastsynctype = 28;
// state->last_cc_sync_time = time(NULL);
// // if (opts->payload == 1)
// // fprintf (stderr, "\n +PANDF ");
// // if (opts->payload == 1)
// // fprintf (stderr, " %s \n", synctest19);
// return (28);
// }
// else if (
// (strcmp (synctest19, "1313311133131331131") == 0 )
// || (strcmp (synctest19, "1313311133331331131") == 0 )
// || (strcmp (synctest19, "1313311133131331111") == 0 )
// || (strcmp (synctest19, "1313311133331331111") == 0 )
// )
// {
// // state->carrier = 1;
// state->carrier = 1;
// state->offset = synctest_pos;
// state->max = ((state->max) + lmax) / 2;
// state->min = ((state->min) + lmin) / 2;
// state->lastsynctype = 29;
// state->last_cc_sync_time = time(NULL);
// // if (opts->payload == 1)
// // fprintf (stderr, "\n -PANDF ");
// // if (opts->payload == 1)
// // fprintf (stderr, " %s \n", synctest19);
// return (29);
// }
// else if (
if (
(strcmp (synctest10, "3131331131") == 0 ) //this seems to be the most common 'correct' pattern on Type-C
|| (strcmp (synctest10, "3331331131") == 0 ) //this one hits on new sync but gives a bad lich code
|| (strcmp (synctest10, "3131331111") == 0 )
|| (strcmp (synctest10, "3331331111") == 0 )
|| (strcmp (synctest10, "3131311131") == 0 ) //First few FSW on NXDN48 Type-C seems to hit this for some reason
)
{
// state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
// state->last_cc_sync_time = time(NULL);
if (state->lastsynctype == 28)
{
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1)
// fprintf (stderr, "\n +FSW ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest10);
return (28);
}
state->lastsynctype = 28;
}
else if (
(strcmp (synctest10, "1313113313") == 0 )
|| (strcmp (synctest10, "1113113313") == 0 )
|| (strcmp (synctest10, "1313113333") == 0 )
|| (strcmp (synctest10, "1113113333") == 0 )
|| (strcmp (synctest10, "1313133313") == 0 ) //
)
{
// state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
// state->last_cc_sync_time = time(NULL);
if (state->lastsynctype == 29)
{
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1)
// fprintf (stderr, "\n -FSW ");
// if (opts->payload == 1)
// fprintf (stderr, " %s \n", synctest10);
return (29);
}
state->lastsynctype = 29;
}
}
#endif //NXDN Sync Type Selection #endif //NXDN Sync Type Selection
//Provoice Conventional -- Some False Positives due to shortened frame sync pattern, so use squelch if possible //Provoice Conventional -- Some False Positives due to shortened frame sync pattern, so use squelch if possible
@@ -1666,8 +1551,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} }
#endif //End Provoice Conventional #endif //End Provoice Conventional
SYNC_TEST_END: ; //do nothing
} // t >= 10 } // t >= 10
if (exitflag == 1) if (exitflag == 1)
@@ -1698,7 +1581,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if ((opts->errorbars == 1) && (opts->verbose > 1) && (state->carrier == 1)) if ((opts->errorbars == 1) && (opts->verbose > 1) && (state->carrier == 1))
{ {
fprintf (stderr,"Sync: no sync\n"); fprintf (stderr,"Sync: no sync\n");
// fprintf (stderr,"Press CTRL + C to close.\n"); fprintf (stderr,"Press CTRL + C to close.\n");
} }
noCarrier (opts, state); noCarrier (opts, state);

View File

@@ -146,8 +146,7 @@ int csvChanImport(dsd_opts * opts, dsd_state * state) //channel map import
return 0; return 0;
} }
//Decimal Variant of Key Import int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support
int csvKeyImportDec(dsd_opts * opts, dsd_state * state) //multi-key support
{ {
char filename[1024] = "filename.csv"; char filename[1024] = "filename.csv";
sprintf (filename, "%s", opts->key_in_file); sprintf (filename, "%s", opts->key_in_file);
@@ -211,48 +210,3 @@ int csvKeyImportDec(dsd_opts * opts, dsd_state * state) //multi-key support
fclose(fp); fclose(fp);
return 0; return 0;
} }
//Hex Variant of Key Import
int csvKeyImportHex(dsd_opts * opts, dsd_state * state) //key import for rc4 keys
{
char filename[1024] = "filename.csv";
sprintf (filename, "%s", opts->key_in_file);
char buffer[BSIZE];
FILE * fp;
fp = fopen(filename, "r");
if (fp == NULL) {
printf("Unable to open file '%s'\n", filename);
exit(1);
}
int row_count = 0;
int field_count = 0;
unsigned long long int keynumber;
while (fgets(buffer, BSIZE, fp)) {
field_count = 0;
row_count++;
if (row_count == 1)
continue; //don't want labels
char * field = strtok(buffer, ","); //seperate by comma
while (field) {
if (field_count == 0)
{
sscanf (field, "%llX", &keynumber);
}
if (field_count == 1)
{
sscanf (field, "%llX", &state->rkey_array[keynumber]);
}
field = strtok(NULL, ",");
field_count++;
}
fprintf (stderr, "Key [%04llX] [%016llX]", keynumber, state->rkey_array[keynumber]);
fprintf (stderr, "\n");
}
fclose(fp);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,59 +2,26 @@
#include "dsd.h" #include "dsd.h"
#include "p25p1_heuristics.h" #include "p25p1_heuristics.h"
//fixed the memory leak, but now random segfaults occur -- double free or corruption (out) or (!prev) void
void resetState (dsd_state * state) resetState (dsd_state * state)
{ {
int i, j; int i, j;
//Dibit Buffer -- Free Allocated Memory
// free (state->dibit_buf);
//Dibit Buffer -- Memset/Init/Allocate Memory
// state->dibit_buf = malloc (sizeof (int) * 1000000); // state->dibit_buf = malloc (sizeof (int) * 1000000);
// state->dibit_buf_p = state->dibit_buf + 200;
state->dibit_buf_p = state->dibit_buf + 200; // memset (state->dibit_buf, 0, sizeof (int) * 200);
memset (state->dibit_buf, 0, sizeof (int) * 200); state->repeat = 0; //not sure yet
state->repeat = 0; //repeat frame? //state->audio_out_buf = malloc (sizeof (short) * 1000000);
//memset (state->audio_out_buf, 0, 100 * sizeof (short));
//Audio Buffer -- Free Allocated Memory //state->audio_out_buf_p = state->audio_out_buf + 100;
free (state->audio_out_buf); //state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
free (state->audio_out_float_buf); //memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
free (state->audio_out_bufR); //state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
free (state->audio_out_float_bufR); //state->audio_out_idx = 0;
//state->audio_out_idx2 = 0;
//Audio Buffer -- Memset/Init/Allocate Memory per slot //state->audio_out_temp_buf_p = state->audio_out_temp_buf;
//state->wav_out_bytes = 0;
//slot 1
state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
state->audio_out_buf = malloc (sizeof (short) * 1000000);
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_idx = 0;
state->audio_out_idx2 = 0;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
//slot 2
state->audio_out_bufR = malloc (sizeof (short) * 1000000);
state->audio_out_float_bufR = malloc (sizeof (float) * 1000000);
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
state->audio_out_buf_pR = state->audio_out_bufR + 100;
memset (state->audio_out_float_bufR, 0, 100 * sizeof (float));
state->audio_out_float_buf_pR = state->audio_out_float_bufR + 100;
state->audio_out_idxR = 0;
state->audio_out_idx2R = 0;
state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
//Sync
state->center = 0; state->center = 0;
state->jitter = -1; state->jitter = -1;
state->synctype = -1; state->synctype = -1;
@@ -64,73 +31,76 @@ void resetState (dsd_state * state)
state->umid = 0; state->umid = 0;
state->minref = -12000; state->minref = -12000;
state->maxref = 12000; state->maxref = 12000;
state->lastsample = 0; state->lastsample = 0;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
{ {
state->sbuf[i] = 0; state->sbuf[i] = 0;
} }
state->sidx = 0; state->sidx = 0;
for (i = 0; i < 1024; i++) for (i = 0; i < 1024; i++)
{ {
state->maxbuf[i] = 15000; state->maxbuf[i] = 15000;
} }
for (i = 0; i < 1024; i++) for (i = 0; i < 1024; i++)
{ {
state->minbuf[i] = -15000; state->minbuf[i] = -15000;
} }
state->midx = 0; state->midx = 0;
state->err_str[0] = 0;
sprintf (state->fsubtype, " ");
sprintf (state->ftype, " ");
state->symbolcnt = 0; state->symbolcnt = 0;
state->rf_mod = 0;
state->numflips = 0; state->numflips = 0;
state->lastsynctype = -1; state->lastsynctype = -1;
state->lastp25type = 0; state->lastp25type = 0;
state->offset = 0; state->offset = 0;
state->carrier = 0; state->carrier = 0;
for (i = 0; i < 25; i++)
//Reset Voice Errors in C0 and C1 (or remaining Codewords in IMBE) {
for (j = 0; j < 16; j++)
{
state->tg[i][j] = 48;
}
}
state->tgcount = 0;
state->lasttg = 0;
state->lastsrc = 0;
state->nac = 0;
state->errs = 0; state->errs = 0;
state->errs2 = 0; state->errs2 = 0;
state->errsR = 0; state->mbe_file_type = -1;
state->errs2R = 0;
//Misc -- may not be needed
state->optind = 0; state->optind = 0;
state->numtdulc = 0; state->numtdulc = 0;
state->firstframe = 0; state->firstframe = 0;
sprintf (state->slot0light, " slot0 ");
sprintf (state->slot1light, " slot1 ");
state->aout_gain = 25;
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (state->algid, "________");
sprintf (state->keyid, "________________");
state->currentslot = 0;
state->cur_mp = malloc (sizeof (mbe_parms));
state->prev_mp = malloc (sizeof (mbe_parms));
state->prev_mp_enhanced = malloc (sizeof (mbe_parms));
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->p25kid = 0;
//unsure if these are still used or ever were used, state->debug_audio_errors = 0;
// memset (state->aout_max_buf, 0, sizeof (float) * 200); state->debug_header_errors = 0;
// state->aout_max_buf_p = state->aout_max_buf; state->debug_header_critical_errors = 0;
// state->aout_max_buf_idx = 0;
// //MBE Specific state->nxdn_last_ran = 0;
// //free the memory before allocating it again -- may not use this // state->payload_algid = 0;
// free (state->cur_mp); // state->payload_algidR = 0;
// free (state->prev_mp); state->dmr_encL = 0;
// free (state->prev_mp_enhanced); state->dmr_encR = 0;
// //memory allocation and init on mbe -- may not use this //each time you run this, it increses memory use by 4MB, massive memory leak
// state->cur_mp = malloc (sizeof (mbe_parms)); //need to revisit this sometime and look into only resetting only the necesary items to let P25 switch between signals (C4FM or Wide) without needing a restart
// state->prev_mp = malloc (sizeof (mbe_parms)); initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over, mitigated with a reset flag
// state->prev_mp_enhanced = malloc (sizeof (mbe_parms));
// mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
//rest the heurestics, we want to do this on each tune, each RF frequency can deviate quite a bit in strength
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
}
//simple function to reset the dibit buffer
void reset_dibit_buffer(dsd_state * state)
{
//Dibit Buffer -- Free Allocated Memory
// free (state->dibit_buf);
//Dibit Buffer -- Memset/Init/Allocate Memory
// state->dibit_buf = malloc (sizeof (int) * 1000000);
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
} }

View File

@@ -250,7 +250,6 @@ int UDPBind (char *hostname, int portno)
return sockfd; return sockfd;
} }
//going to leave this function available, even if completely switched over to rtl_dev_tune now, may be useful in the future
void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency) void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency)
{ {
int handle; int handle;
@@ -275,5 +274,8 @@ void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency)
address.sin_port = htons(udp_port); address.sin_port = htons(udp_port);
sendto(handle, data, 5, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in)); sendto(handle, data, 5, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
//BUGFIX: This was causing an indefinite number of UDP sockets to stay open on each tune request
//we open a new socket with each request, so we need to close the socket after writing to it
//this would cause the tuning to stop after x number of tune attempts (few hours? on a busy system)
close (handle); //close socket after sending. close (handle); //close socket after sending.
} }

View File

@@ -82,24 +82,35 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
} }
// Read the new sample from the input // Read the new sample from the input
if(opts->audio_in_type == 0) //pulse audio if(opts->audio_in_type == 0) // && state->menuopen == 0 still not quite working
{ {
pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL ); pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL );
} //look into how processAudio handles playback, not sure if latency issues, or garbage sample values crash pulse when written
// if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample < 32767 && sample > -32767)
if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample != 0)
{
state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here?
pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL);
}
//playback is wrong, depends on samples_per_symbol, maybe make a buffer and store first?
//making buffer might also fix raw audio monitoring as well
if (opts->wav_out_file_raw[0] != 0) //if set for recording sample raw files
{
//writeRawSample (opts, state, sample);
}
else if (opts->audio_in_type == 5) //OSS
{
read (opts->audio_in_fd, &sample, 2);
} }
//stdin only, wav files moving to new number //stdin only, wav files moving to new number
else if (opts->audio_in_type == 1) //won't work in windows, needs posix pipe (mintty) else if (opts->audio_in_type == 1)
{ {
result = sf_read_short(opts->audio_in_file, &sample, 1); result = sf_read_short(opts->audio_in_file, &sample, 1);
if(result == 0) if(result == 0)
{ {
//cleanupAndExit (opts, state);
sf_close(opts->audio_in_file); sf_close(opts->audio_in_file);
cleanupAndExit (opts, state); opts->audio_in_type = 0; //set input type
openPulseInput(opts); //open pulse inpput
sample = 0; //send zero sample
} }
} }
//wav files, same but using seperate value so we can still manipulate ncurses menu //wav files, same but using seperate value so we can still manipulate ncurses menu
@@ -111,19 +122,10 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{ {
sf_close(opts->audio_in_file); sf_close(opts->audio_in_file);
fprintf (stderr, "\nEnd of %s\n", opts->audio_in_dev); opts->audio_in_type = 0; //set input type
//open pulse input if we are pulse output AND using ncurses terminal openPulseInput(opts); //open pulse inpput
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1) sample = 0; //send zero sample
{
opts->audio_in_type = 0; //set input type
openPulseInput(opts); //open pulse input
}
//else cleanup and exit
else
{
if (opts->use_ncurses_terminal == 1) ncursesClose(opts);
cleanupAndExit(opts, state);
}
} }
} }
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
@@ -137,72 +139,13 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here? state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here?
pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL); pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL);
} }
opts->rtl_rms = rtl_return_rms();
#endif #endif
} }
//tcp socket input from SDR++ -- now with 1 retry if connection is broken //tcp socket input from SDR++
else if (opts->audio_in_type == 8) else if (opts->audio_in_type == 8)
{ {
#ifdef AERO_BUILD
result = sf_read_short(opts->tcp_file_in, &sample, 1);
if(result == 0) {
fprintf (stderr, "\nConnection to TCP Server Interrupted. Trying again in 3 seconds.\n");
sample = 0;
sf_close(opts->tcp_file_in); //close current connection on this end
sleep (3); //halt all processing and wait 3 seconds
//attempt to reconnect to socket
opts->tcp_sockfd = 0;
opts->tcp_sockfd = Connect(opts->tcp_hostname, opts->tcp_portno);
if (opts->tcp_sockfd != 0)
{
//reset audio input stream
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->samplerate=opts->wav_sample_rate;
opts->audio_in_file_info->channels=1;
opts->audio_in_file_info->seekable=0;
opts->audio_in_file_info->format=SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE;
opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
if(opts->tcp_file_in == NULL)
{
fprintf(stderr, "Error, couldn't Reconnect to TCP with libsndfile: %s\n", sf_strerror(NULL));
}
else fprintf (stderr, "TCP Socket Reconnected Successfully.\n");
}
else fprintf (stderr, "TCP Socket Connection Error.\n");
//now retry reading sample
result = sf_read_short(opts->tcp_file_in, &sample, 1);
if (result == 0) {
sf_close(opts->tcp_file_in);
opts->audio_in_type = 0; //set input type
opts->tcp_sockfd = 0; //added this line so we will know if it connected when using ncurses terminal keyboard shortcut
//openPulseInput(opts); //open pulse inpput
sample = 0; //zero sample on bad result, keep the ball rolling
//open pulse input if we are pulse output AND using ncurses terminal
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1)
{
fprintf (stderr, "Connection to TCP Server Disconnected.\n");
fprintf (stderr, "Opening Pulse Audio Input.\n");
opts->audio_in_type = 0; //set input type
openPulseInput(opts); //open pulse input
}
//else cleanup and exit
else
{
fprintf (stderr, "Connection to TCP Server Disconnected.\n");
fprintf (stderr, "Closing DSD-FME.\n");
if (opts->use_ncurses_terminal == 1) ncursesClose(opts);
cleanupAndExit(opts, state);
}
}
}
#else
result = sf_read_short(opts->tcp_file_in, &sample, 1); result = sf_read_short(opts->tcp_file_in, &sample, 1);
if(result == 0) { if(result == 0) {
fprintf (stderr, "\nConnection to TCP Server Interrupted. Trying again in 3 seconds.\n"); fprintf (stderr, "\nConnection to TCP Server Interrupted. Trying again in 3 seconds.\n");
@@ -243,24 +186,28 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
} }
} }
#endif
} }
//UDP Socket input...not working correct. Reads samples, but no sync
else if (opts->audio_in_type == 6)
{
//I think this doesn't get the entire dgram when we run sf_read_short on the udp dgram
result = sf_read_short(opts->udp_file_in, &sample, 1);
// if (sample != 0)
// fprintf (stderr, "Result = %d Sample = %d \n", result, sample);
}
if (opts->use_cosine_filter) if (opts->use_cosine_filter)
{ {
if ( (state->lastsynctype >= 10 && state->lastsynctype <= 13) || state->lastsynctype == 32 || state->lastsynctype == 33 if ( (state->lastsynctype >= 10 && state->lastsynctype <= 13) || state->lastsynctype == 32 || state->lastsynctype == 33 || state->lastsynctype == 34)
|| state->lastsynctype == 34 || state->lastsynctype == 30 || state->lastsynctype == 31)
{ {
sample = dmr_filter(sample); sample = dmr_filter(sample);
} }
else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||state->lastsynctype == 16 || state->lastsynctype == 17) else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||
{ state->lastsynctype == 16 || state->lastsynctype == 17 ||
sample = m17_filter(sample);
}
else if (
state->lastsynctype == 20 || state->lastsynctype == 21 || state->lastsynctype == 20 || state->lastsynctype == 21 ||
state->lastsynctype == 22 || state->lastsynctype == 23 || state->lastsynctype == 22 || state->lastsynctype == 23 ||
state->lastsynctype == 24 || state->lastsynctype == 25 || state->lastsynctype == 24 || state->lastsynctype == 25 ||
@@ -469,12 +416,6 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
} }
#endif #endif
//test throttle on wav input files
if (opts->audio_in_type == 2)
{
if (state->use_throttle == 1) usleep(.003); //very environment specific, tuning to cygwin
}
//read op25/fme symbol bin files //read op25/fme symbol bin files
if (opts->audio_in_type == 4) if (opts->audio_in_type == 4)
{ {
@@ -491,27 +432,14 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
useconds_t stime = state->symbol_throttle; useconds_t stime = state->symbol_throttle;
if (state->use_throttle == 1) if (state->use_throttle == 1)
{ {
// usleep(stime); usleep(stime);
usleep(.003); //very environment specific, tuning to cygwin
} }
//fprintf(stderr, "%d", state->symbolc); //fprintf(stderr, "%d", state->symbolc);
if( feof(opts->symbolfile) ) if( feof(opts->symbolfile) )
{ {
// opts->audio_in_type = 0; //switch to pulse after playback, ncurses terminal can initiate replay if wanted opts->audio_in_type = 0; //switch to pulse after playback, ncurses terminal can initiate replay if wanted
fclose(opts->symbolfile); fclose(opts->symbolfile);
fprintf (stderr, "\nEnd of %s\n", opts->audio_in_dev); openPulseInput(opts);
//open pulse input if we are pulse output AND using ncurses terminal
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1)
{
opts->audio_in_type = 0; //set input type
openPulseInput(opts); //open pulse input
}
//else cleanup and exit
else
{
if (opts->use_ncurses_terminal == 1) ncursesClose(opts);
cleanupAndExit(opts, state);
}
} }
//assign symbol/dibit values based on modulation type //assign symbol/dibit values based on modulation type

View File

@@ -298,11 +298,9 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 3) //rtl dongle if (opts->audio_in_type == 3) //rtl dongle
{ {
#ifdef USE_RTLSDR rtl_udp_tune(opts, state, state->trunk_lcn_freq[lcn-1]);
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn; state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
#endif
} }
} }
@@ -430,11 +428,9 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 3) //rtl dongle if (opts->audio_in_type == 3) //rtl dongle
{ {
#ifdef USE_RTLSDR rtl_udp_tune(opts, state, state->trunk_lcn_freq[lcn-1]);
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn; state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
#endif
} }
} }

746
src/m17.c
View File

@@ -1,746 +0,0 @@
/*-------------------------------------------------------------------------------
* m17.c
* M17 Decoder (WIP)
*
* m17_scramble Bit Array from SDR++
* CRC16 from M17-Implementations (thanks again, sp5wwp)
*
* LWVMOBILE
* 2023-07 DSD-FME Florida Man Edition
*-----------------------------------------------------------------------------*/
#include "dsd.h"
//try to find a fancy lfsr or calculation for this and not an array if possible
uint8_t m17_scramble[369] = {
1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1
};
char b40[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
uint8_t p1[62] = {
1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1
};
//from M17_Implementations -- sp5wwp -- should have just looked here to begin with
//this setup looks very similar to the OP25 variant of crc16, but with a few differences (uses packed bytes)
uint16_t crc16m17(const uint8_t *in, const uint16_t len)
{
uint32_t crc = 0xFFFF; //init val
uint16_t poly = 0x5935;
for(uint16_t i=0; i<len; i++)
{
crc^=in[i]<<8;
for(uint8_t j=0; j<8; j++)
{
crc<<=1;
if(crc&0x10000)
crc=(crc^poly)&0xFFFF;
}
}
return crc&(0xFFFF);
}
void M17decodeCSD(dsd_state * state, unsigned long long int dst, unsigned long long int src)
{
//evaluate dst and src, and determine if they need to be converted to calsign
int i, j;
char c;
unsigned long long int value;
if (dst == 0xFFFFFFFFFFFF)
fprintf (stderr, " DST: BROADCAST");
else if (dst == 0)
fprintf (stderr, " DST: RESERVED %012llx", dst);
else if (dst >= 0xEE6B28000000)
fprintf (stderr, " DST: RESERVED %012llx", dst);
else
{
fprintf (stderr, " DST: ");
for (i = 0; i < 9; i++)
{
c = b40[dst % 40];
state->m17_dst_csd[i] = c;
fprintf (stderr, "%c", c);
dst = dst / 40;
}
//assign completed CSD to a more useful string instead
sprintf (state->m17_dst_str, "%c%c%c%c%c%c%c%c%c",
state->m17_dst_csd[0], state->m17_dst_csd[1], state->m17_dst_csd[2], state->m17_dst_csd[3],
state->m17_dst_csd[4], state->m17_dst_csd[5], state->m17_dst_csd[6], state->m17_dst_csd[7], state->m17_dst_csd[8]);
//debug
// fprintf (stderr, "DT: %s", state->m17_dst_str);
}
if (src == 0xFFFFFFFFFFFF)
fprintf (stderr, " SRC: UNKNOWN FFFFFFFFFFFF");
else if (src == 0)
fprintf (stderr, " SRC: RESERVED %012llx", src);
else if (src >= 0xEE6B28000000)
fprintf (stderr, " SRC: RESERVED %012llx", src);
else
{
fprintf (stderr, " SRC: ");
for (i = 0; i < 9; i++)
{
c = b40[src % 40];
state->m17_src_csd[i] = c;
fprintf (stderr, "%c", c);
src = src / 40;
}
//assign completed CSD to a more useful string instead
sprintf (state->m17_src_str, "%c%c%c%c%c%c%c%c%c",
state->m17_src_csd[0], state->m17_src_csd[1], state->m17_src_csd[2], state->m17_src_csd[3],
state->m17_src_csd[4], state->m17_src_csd[5], state->m17_src_csd[6], state->m17_src_csd[7], state->m17_src_csd[8]);
//debug
// fprintf (stderr, "ST: %s", state->m17_src_str);
}
//debug
// fprintf (stderr, " DST: %012llX SRC: %012llX", state->m17_dst, state->m17_src);
}
void M17decodeLSF(dsd_state * state)
{
int i;
unsigned long long int lsf_dst = (unsigned long long int)ConvertBitIntoBytes(&state->m17_lsf[0], 48);
unsigned long long int lsf_src = (unsigned long long int)ConvertBitIntoBytes(&state->m17_lsf[48], 48);
uint16_t lsf_type = (uint16_t)ConvertBitIntoBytes(&state->m17_lsf[96], 16);
//this is the way the manual/code expects you to read these bits
uint8_t lsf_ps = (lsf_type >> 0) & 0x1;
uint8_t lsf_dt = (lsf_type >> 1) & 0x3;
uint8_t lsf_et = (lsf_type >> 3) & 0x3;
uint8_t lsf_es = (lsf_type >> 5) & 0x3;
uint8_t lsf_cn = (lsf_type >> 7) & 0xF;
uint8_t lsf_rs = (lsf_type >> 11) & 0x1F;
//store this so we can reference it for playing voice and/or decoding data, dst/src etc
state->m17_str_dt = lsf_dt;
state->m17_dst = lsf_dst;
state->m17_src = lsf_src;
fprintf (stderr, "\n");
//packet or stream
if (lsf_ps == 0) fprintf (stderr, " P-");
if (lsf_ps == 1) fprintf (stderr, " S-");
fprintf (stderr, " CAN: %d", lsf_cn);
M17decodeCSD(state, lsf_dst, lsf_src);
if (lsf_et != 0) fprintf (stderr, " ENC");
if (lsf_dt == 0) fprintf (stderr, " Reserved");
if (lsf_dt == 1) fprintf (stderr, " Data");
if (lsf_dt == 2) fprintf (stderr, " Voice (3200bps)");
if (lsf_dt == 3) fprintf (stderr, " Voice + Data");
if (lsf_rs != 0) fprintf (stderr, " RS: %02X", lsf_rs);
if (lsf_et == 1) fprintf (stderr, " AES-CTR");
if (lsf_et == 2) fprintf (stderr, " Scrambler - %d", lsf_es);
state->m17_enc = lsf_et;
state->m17_enc_st = lsf_es;
//pack meta bits into 14 bytes
for (i = 0; i < 14; i++)
state->m17_meta[i] = (uint8_t)ConvertBitIntoBytes(&state->m17_lsf[(i*8)+112], 8);
//Examine the Meta data
if (lsf_et == 0 && state->m17_meta[0] != 0) //not sure if this applies universally, or just to text data byte 0 for null data
{
fprintf (stderr, " Meta:");
if (lsf_es == 0) fprintf (stderr, " Text Data");
if (lsf_es == 1) fprintf (stderr, " GNSS Pos");
if (lsf_es == 2) fprintf (stderr, " Extended CSD");
if (lsf_es == 3) fprintf (stderr, " Reserved");
}
if (lsf_et == 1)
{
fprintf (stderr, " IV: ");
for (i = 0; i < 14; i++)
fprintf (stderr, "%02X", state->m17_meta[i]);
}
}
int M17processLICH(dsd_state * state, dsd_opts * opts, uint8_t lich_bits[96])
{
int i, j, err;
err = 0;
uint8_t lich[4][24];
uint8_t lich_decoded[48];
uint8_t temp[96];
bool g[4];
//for testing bit arrangement vs the crc code
uint8_t bs[240];
memset(bs, 1, sizeof(bs));
uint16_t crc_cmp = 0;
uint16_t crc_ext = 0;
uint8_t crc_err = 0;
memset(lich, 0, sizeof(lich));
memset(lich_decoded, 0, sizeof(lich_decoded));
memset(temp, 0, sizeof(temp));
//execute golay 24,12 or 4 24-bit chunks and reorder into 4 12-bit chunks
for (i = 0; i < 4; i++)
{
g[i] = TRUE;
for (j = 0; j < 24; j++)
lich[i][j] = lich_bits[(i*24)+j];
g[i] = Golay_24_12_decode(lich[i]);
if(g[i] == FALSE) err = -1;
for (j = 0; j < 12; j++)
lich_decoded[i*12+j] = lich[i][j];
}
uint8_t lich_counter = (uint8_t)ConvertBitIntoBytes(&lich_decoded[40], 3); //lich_cunt
uint8_t lich_reserve = (uint8_t)ConvertBitIntoBytes(&lich_decoded[43], 5); //lich_reserved
if (err == 0)
fprintf (stderr, "LC: %d/6 ", lich_counter+1);
else fprintf (stderr, "LICH G24 ERR");
if (err = 0 && lich_reserve != 0) fprintf(stderr, " LRS: %d", lich_reserve);
//transfer to storage
for (i = 0; i < 40; i++)
state->m17_lsf[lich_counter*40+i] = lich_decoded[i];
if (opts->payload == 1)
{
fprintf (stderr, " LICH: ");
for (i = 0; i < 6; i++)
fprintf (stderr, "[%02X]", (uint8_t)ConvertBitIntoBytes(&lich_decoded[i*8], 8));
}
uint8_t lsf_packed[30];
memset (lsf_packed, 0, sizeof(lsf_packed));
if (lich_counter == 5)
{
//need to pack bytes for the sw5wwp variant of the crc (might as well, may be useful in the future)
for (i = 0; i < 30; i++)
lsf_packed[i] = (uint8_t)ConvertBitIntoBytes(&state->m17_lsf[i*8], 8);
crc_cmp = crc16m17(lsf_packed, 28);
crc_ext = (uint16_t)ConvertBitIntoBytes(&state->m17_lsf[224], 16);
if (crc_cmp != crc_ext) crc_err = 1;
if (crc_err == 0)
M17decodeLSF(state);
if (opts->payload == 1)
{
fprintf (stderr, "\n LSF: ");
for (i = 0; i < 30; i++)
{
if (i == 15) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", lsf_packed[i]);
}
}
memset (state->m17_lsf, 1, sizeof(state->m17_lsf));
//debug
// fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp);
if (crc_err == 1) fprintf (stderr, " EMB LSF CRC ERR");
}
return err;
}
void M17processCodec2_1600(dsd_opts * opts, dsd_state * state, uint8_t payload[128])
{
//If payload is the same from the stream in this mode, I suppose we could use this area to parse
//or send off the remaining data to be handled or decoded , or just print out the raw data bytes
int i;
unsigned char voice1[8]; //codec2_bytes_per_frame
unsigned char voice2[8];
for (i = 0; i < 8; i++)
{
voice1[i] = (unsigned char)ConvertBitIntoBytes(&payload[i*8+0], 8);
voice2[i] = (unsigned char)ConvertBitIntoBytes(&payload[i*8+64], 8);
}
//TODO: Add some decryption methods
if (state->m17_enc != 0)
{
//process scrambler or AES-CTR decryption
//(no AES-CTR right now, Scrambler should be easy enough)
}
if (opts->payload == 1)
{
fprintf (stderr, "\n CODEC2: ");
for (i = 0; i < 8; i++)
fprintf (stderr, "%02X", voice1[i]);
fprintf (stderr, " (1600)");
fprintf (stderr, "\n LSDATA: "); //low speed data
for (i = 0; i < 8; i++)
fprintf (stderr, "%02X", voice2[i]);
}
#ifdef USE_CODEC2
size_t nsam;
nsam = 320; //codec2_samples_per_frame(state->codec2_1600);
short samp1[nsam];
// short samp2[nsam];
memset (samp1, 0, sizeof(samp1));
// memset (samp2, 0, sizeof(samp2));
codec2_decode(state->codec2_1600, samp1, voice1);
// codec2_decode(state->codec2_1600, samp2, voice2);
if (opts->audio_out_type == 0 && state->m17_enc == 0)
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
// pa_simple_write(opts->pulse_digi_dev_out, samp2, nsam*2, NULL);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0)
{
write (opts->audio_out_fd, samp1, nsam*2);
// write (opts->audio_out_fd, samp2, nsam*2);
}
//WIP: Wav file saving -- still need a way to open/close/label wav files similar to call history
if(opts->wav_out_f != NULL && state->m17_enc == 0)
{
sf_write_short(opts->wav_out_f, samp1, nsam);
// sf_write_short(opts->wav_out_f, samp2, nsam);
}
//TODO: Codec2 Raw file saving
// if(mbe_out_dir)
// {
// }
#endif
}
void M17processCodec2_3200(dsd_opts * opts, dsd_state * state, uint8_t payload[128])
{
int i;
unsigned char voice1[8]; //codec2_bytes_per_frame
unsigned char voice2[8];
for (i = 0; i < 8; i++)
{
voice1[i] = (unsigned char)ConvertBitIntoBytes(&payload[i*8+0], 8);
voice2[i] = (unsigned char)ConvertBitIntoBytes(&payload[i*8+64], 8);
}
//TODO: Add some decryption methods
if (state->m17_enc != 0)
{
//process scrambler or AES-CTR decryption
//(no AES-CTR right now, Scrambler should be easy enough)
}
if (opts->payload == 1)
{
fprintf (stderr, "\n CODEC2: ");
for (i = 0; i < 8; i++)
fprintf (stderr, "%02X", voice1[i]);
fprintf (stderr, " (3200)");
fprintf (stderr, "\n CODEC2: ");
for (i = 0; i < 8; i++)
fprintf (stderr, "%02X", voice2[i]);
fprintf (stderr, " (3200)");
}
#ifdef USE_CODEC2
size_t nsam;
nsam = 160; //codec2_samples_per_frame(state->codec2_3200);
short samp1[nsam];
short samp2[nsam];
memset (samp1, 0, sizeof(samp1));
memset (samp2, 0, sizeof(samp2));
codec2_decode(state->codec2_3200, samp1, voice1);
codec2_decode(state->codec2_3200, samp2, voice2);
if (opts->audio_out_type == 0 && state->m17_enc == 0)
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
pa_simple_write(opts->pulse_digi_dev_out, samp2, nsam*2, NULL);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0)
{
write (opts->audio_out_fd, samp1, nsam*2);
write (opts->audio_out_fd, samp2, nsam*2);
}
//WIP: Wav file saving -- still need a way to open/close/label wav files similar to call history
if(opts->wav_out_f != NULL && state->m17_enc == 0)
{
sf_write_short(opts->wav_out_f, samp1, nsam);
sf_write_short(opts->wav_out_f, samp2, nsam);
}
//TODO: Codec2 Raw file saving
// if(mbe_out_dir)
// {
// }
#endif
}
void M17prepareStream(dsd_opts * opts, dsd_state * state, uint8_t m17_bits[368])
{
int i, j, k, x;
uint8_t m17_punc[310]; //25 * 11 = 275
memset (m17_punc, 0, sizeof(m17_punc));
for (i = 0; i < 272; i++)
m17_punc[i] = m17_bits[i+96];
//depuncture the bits
uint8_t m17_depunc[310]; //25 * 12 = 300
memset (m17_depunc, 0, sizeof(m17_depunc));
k = 0; x = 0;
for (i = 0; i < 25; i++)
{
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = m17_punc[x++];
m17_depunc[k++] = 0;
}
//setup the convolutional decoder
uint8_t temp[300];
uint8_t s0;
uint8_t s1;
uint8_t m_data[28];
uint8_t trellis_buf[400];
memset (trellis_buf, 0, sizeof(trellis_buf));
memset (temp, 0, sizeof (temp));
memset (m_data, 0, sizeof (m_data));
for (i = 0; i < 296; i++)
temp[i] = m17_depunc[i] << 1;
CNXDNConvolution_start();
for (i = 0; i < 148; i++)
{
s0 = temp[(2*i)];
s1 = temp[(2*i)+1];
CNXDNConvolution_decode(s0, s1);
}
CNXDNConvolution_chainback(m_data, 144);
//144/8 = 18, last 4 (144-148) are trailing zeroes
for(i = 0; i < 18; i++)
{
trellis_buf[(i*8)+0] = (m_data[i] >> 7) & 1;
trellis_buf[(i*8)+1] = (m_data[i] >> 6) & 1;
trellis_buf[(i*8)+2] = (m_data[i] >> 5) & 1;
trellis_buf[(i*8)+3] = (m_data[i] >> 4) & 1;
trellis_buf[(i*8)+4] = (m_data[i] >> 3) & 1;
trellis_buf[(i*8)+5] = (m_data[i] >> 2) & 1;
trellis_buf[(i*8)+6] = (m_data[i] >> 1) & 1;
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
}
//load m_data into bits for either data packets or voice packets
uint8_t payload[128];
uint8_t end = 9;
uint16_t fn = 0;
memset (payload, 0, sizeof(payload));
end = trellis_buf[0];
fn = (uint16_t)ConvertBitIntoBytes(&trellis_buf[1], 15);
if (opts->payload == 1)
fprintf (stderr, " FSN: %05d", fn);
if (end == 1)
fprintf (stderr, " END;");
for (i = 0; i < 128; i++)
payload[i] = trellis_buf[i+16];
if (state->m17_str_dt == 2)
M17processCodec2_3200(opts, state, payload);
else if (state->m17_str_dt == 3)
M17processCodec2_1600(opts, state, payload);
else if (state->m17_str_dt == 1) fprintf (stderr, " DATA;");
else if (state->m17_str_dt == 0) fprintf (stderr, " RES;");
// else fprintf (stderr, " UNK;");
if (opts->payload == 1 && state->m17_str_dt < 2)
{
fprintf (stderr, "\n STREAM: ");
for (i = 0; i < 18; i++)
fprintf (stderr, "[%02X]", (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8));
}
}
void processM17STR(dsd_opts * opts, dsd_state * state)
{
int i, x;
//NOTE: adding more space for dbuf seems to fix the memory issue, but I don't think this is
//the culprit, not entirely sure what is going on here, but the issue with Cygwin (32-bit)
//not working at all with this also is fixed by this and I can't seem to figure out why
//its probably something really dumb that I am completely blind on seeing here for some reason
uint8_t dbuf[384]; //384-bit frame - 16-bit (8 symbol) sync pattern (184 dibits)
uint8_t m17_rnd_bits[368]; //368 bits that are still scrambled (randomized)
uint8_t m17_int_bits[368]; //368 bits that are still interleaved
uint8_t m17_bits[368]; //368 bits that have been de-interleaved and de-scramble
uint8_t lich_bits[96];
int lich_err = -1;
memset (dbuf, 0, sizeof(dbuf));
memset (m17_rnd_bits, 0, sizeof(m17_rnd_bits));
memset (m17_int_bits, 0, sizeof(m17_int_bits));
memset (m17_bits, 0, sizeof(m17_bits));
memset (lich_bits, 0, sizeof(lich_bits));
//load dibits into dibit buffer
for (i = 0; i < 184; i++)
dbuf[i] = (uint8_t) getDibit(opts, state);
//convert dbuf into a bit array
for (i = 0; i < 184; i++)
{
m17_rnd_bits[i*2+0] = (dbuf[i] >> 1) & 1;
m17_rnd_bits[i*2+1] = (dbuf[i] >> 0) & 1;
}
//descramble the frame
for (i = 0; i < 368; i++)
m17_int_bits[i] = (m17_rnd_bits[i] ^ m17_scramble[i]) & 1;
//deinterleave the bit array using Quadratic Permutation Polynomial
//function π(x) = (45x + 92x^2 ) mod 368
for (i = 0; i < 368; i++)
{
x = ((45*i)+(92*i*i)) % 368;
m17_bits[i] = m17_int_bits[x];
}
for (i = 0; i < 96; i++)
lich_bits[i] = m17_bits[i];
//check lich first, and handle LSF chunk and completed LSF
lich_err = M17processLICH(state, opts, lich_bits);
if (lich_err == 0)
M17prepareStream(opts, state, m17_bits);
// if (lich_err != 0) state->lastsynctype = -1; //disable
//ending linebreak
fprintf (stderr, "\n");
} //end processM17STR
void processM17LSF(dsd_opts * opts, dsd_state * state)
{
//NOTE1: Pretty sure the flow here is all correct, but the initial (and only)
//LSF frame is demodulated incorrectly, so more than likely, this frame will
//always be bad since there is only one sent before STR
//NOTE2: Even with the preamble detection and LSF sync, we still get bad decode on this
int i, j, k, x;
uint8_t dbuf[384]; //384-bit frame - 16-bit (8 symbol) sync pattern (184 dibits)
uint8_t m17_rnd_bits[500]; //368 bits that are still scrambled (randomized)
uint8_t m17_int_bits[500]; //368 bits that are still interleaved
uint8_t m17_bits[500]; //368 bits that have been de-interleaved and de-scramble
uint8_t m17_depunc[500]; //488 bits after depuncturing
memset (dbuf, 0, sizeof(dbuf));
memset (m17_rnd_bits, 0, sizeof(m17_rnd_bits));
memset (m17_int_bits, 0, sizeof(m17_int_bits));
memset (m17_bits, 0, sizeof(m17_bits));
memset (m17_depunc, 0, sizeof(m17_depunc));
//load dibits into dibit buffer
for (i = 0; i < 184; i++)
dbuf[i] = (uint8_t) getDibit(opts, state);
//convert dbuf into a bit array
for (i = 0; i < 184; i++)
{
m17_rnd_bits[i*2+0] = (dbuf[i] >> 1) & 1;
m17_rnd_bits[i*2+1] = (dbuf[i] >> 0) & 1;
}
//descramble the frame
for (i = 0; i < 368; i++)
m17_int_bits[i] = (m17_rnd_bits[i] ^ m17_scramble[i]) & 1;
//deinterleave the bit array using Quadratic Permutation Polynomial
//function π(x) = (45x + 92x^2 ) mod 368
for (i = 0; i < 368; i++)
{
x = ((45*i)+(92*i*i)) % 368;
m17_bits[i] = m17_int_bits[x];
}
j = 0; k = 0; x = 0;
// P1 Depuncture
for (i = 0; i < 488; i++)
{
if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
else m17_depunc[x++] = 1;
if (k == 61) k = 0; //61 -- should reset 8 times againt the array
}
//debug -- values seem okay at end of run
// fprintf (stderr, "K = %d; J = %d; X = %d", k, j, x);
//setup the convolutional decoder
uint8_t temp[500];
uint8_t s0;
uint8_t s1;
uint8_t m_data[32];
uint8_t trellis_buf[400];
memset (trellis_buf, 0, sizeof(trellis_buf));
memset (temp, 0, sizeof (temp));
memset (m_data, 0, sizeof (m_data));
for (i = 0; i < 488; i++)
temp[i] = m17_depunc[i] << 1;
CNXDNConvolution_start();
for (i = 0; i < 244; i++)
{
s0 = temp[(2*i)];
s1 = temp[(2*i)+1];
CNXDNConvolution_decode(s0, s1);
}
CNXDNConvolution_chainback(m_data, 240);
//244/8 = 30, last 4 (244-248) are trailing zeroes
for(i = 0; i < 30; i++)
{
trellis_buf[(i*8)+0] = (m_data[i] >> 7) & 1;
trellis_buf[(i*8)+1] = (m_data[i] >> 6) & 1;
trellis_buf[(i*8)+2] = (m_data[i] >> 5) & 1;
trellis_buf[(i*8)+3] = (m_data[i] >> 4) & 1;
trellis_buf[(i*8)+4] = (m_data[i] >> 3) & 1;
trellis_buf[(i*8)+5] = (m_data[i] >> 2) & 1;
trellis_buf[(i*8)+6] = (m_data[i] >> 1) & 1;
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
}
memset (state->m17_lsf, 0, sizeof(state->m17_lsf));
memcpy (state->m17_lsf, trellis_buf, 240);
uint8_t lsf_packed[30];
memset (lsf_packed, 0, sizeof(lsf_packed));
//need to pack bytes for the sw5wwp variant of the crc (might as well, may be useful in the future)
for (i = 0; i < 30; i++)
lsf_packed[i] = (uint8_t)ConvertBitIntoBytes(&state->m17_lsf[i*8], 8);
uint16_t crc_cmp = crc16m17(lsf_packed, 28);
uint16_t crc_ext = (uint16_t)ConvertBitIntoBytes(&state->m17_lsf[224], 16);
int crc_err = 0;
if (crc_cmp != crc_ext) crc_err = 1;
if (crc_err == 0)
M17decodeLSF(state);
if (opts->payload == 1)
{
fprintf (stderr, "\n LSF: ");
for (i = 0; i < 30; i++)
{
if (i == 15) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", lsf_packed[i]);
}
}
//debug
// fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp);
if (crc_err == 1) fprintf (stderr, " CRC ERR");
//ending linebreak
fprintf (stderr, "\n");
} //end processM17LSF

View File

@@ -36,13 +36,13 @@
/* Global variables ---------------------------------------------------------*/ /* Global variables ---------------------------------------------------------*/
static const uint8_t CNXDNConvolution_BIT_MASK_TABLE[8] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; static const uint8_t CNXDNConvolution_BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~CNXDNConvolution_BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & CNXDNConvolution_BIT_MASK_TABLE[(i)&7])
static const uint8_t CNXDNConvolution_BRANCH_TABLE1[8] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U}; static const uint8_t CNXDNConvolution_BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
static const uint8_t CNXDNConvolution_BRANCH_TABLE2[8] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U}; static const uint8_t CNXDNConvolution_BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
static const unsigned int CNXDNConvolution_NUM_OF_STATES_D2 = 8U; static const unsigned int CNXDNConvolution_NUM_OF_STATES_D2 = 8U;
static const unsigned int CNXDNConvolution_NUM_OF_STATES = 16U; static const unsigned int CNXDNConvolution_NUM_OF_STATES = 16U;

View File

@@ -25,9 +25,7 @@
#include "dsd.h" #include "dsd.h"
#include "nxdn_const.h" #include "nxdn_const.h"
//NOTE: Descrambling was having an issue without a value inside the brackets, but only when static const uint8_t scramble_t[] = { //values are the position values we need to invert in the descramble
//the PARITY table was disabled, was this due to a memory issue or overflow?
static const uint8_t scramble_t[182] = { //values are the position values we need to invert in the descramble
2, 5, 6, 7, 10, 12, 14, 16, 17, 22, 23, 25, 26, 27, 28, 30, 33, 34, 36, 37, 38, 41, 45, 47, 2, 5, 6, 7, 10, 12, 14, 16, 17, 22, 23, 25, 26, 27, 28, 30, 33, 34, 36, 37, 38, 41, 45, 47,
52, 54, 56, 57, 59, 62, 63, 64, 65, 66, 67, 69, 70, 73, 76, 79, 81, 82, 84, 85, 86, 87, 88, 52, 54, 56, 57, 59, 62, 63, 64, 65, 66, 67, 69, 70, 73, 76, 79, 81, 82, 84, 85, 86, 87, 88,
89, 92, 95, 96, 98, 100, 103, 104, 107, 108, 116, 117, 121, 122, 125, 127, 131, 132, 134, 89, 92, 95, 96, 98, 100, 103, 104, 107, 108, 116, 117, 121, 122, 125, 127, 131, 132, 134,
@@ -35,6 +33,11 @@ static const uint8_t scramble_t[182] = { //values are the position values we nee
168, 170, 171, 174, 175, 176, 177, 181 168, 170, 171, 174, 175, 176, 177, 181
}; };
static const int PARITY[] = {
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0,
1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1,
1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
//decoding functions here //decoding functions here
void nxdn_descramble(uint8_t dibits[], int len) void nxdn_descramble(uint8_t dibits[], int len)
@@ -118,23 +121,26 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
check = check | trellis_buf[84+i]; //80 check = check | trellis_buf[84+i]; //80
} }
if (crc != check)
{
fprintf (stderr, " FACCH");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, trellis_buf); if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, trellis_buf);
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf); else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
if (opts->payload == 1) if (opts->payload == 1)
{ {
fprintf (stderr, "\n"); fprintf (stderr, "\n");
fprintf (stderr, " FACCH1 Payload "); fprintf (stderr, " FACCH Payload ");
for (int i = 0; i < 12; i++) for (int i = 0; i < 12; i++)
{ {
fprintf (stderr, "[%02X]", m_data[i]); fprintf (stderr, "[%02X]", m_data[i]);
} }
if (crc != check && opts->payload == 1) // fprintf (stderr, " - %03X %03X", check, crc);
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
} }
} }
@@ -245,14 +251,16 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
state->nxdn_last_ran = ran; state->nxdn_last_ran = ran;
} }
fprintf (stderr, "PF 1/1");
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch); if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch);
// else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, nsf_sacch); else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, nsf_sacch);
//I'm placing this here, my observation is that SACCH NSF if (crc != check)
//is almost always, if not always, just IDLE {
else fprintf (stderr, " IDLE"); fprintf (stderr, " SACCH NSF");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
if (opts->payload == 1) if (opts->payload == 1)
{ {
@@ -261,15 +269,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
{ {
fprintf (stderr, "[%02X]", m_data[i]); fprintf (stderr, "[%02X]", m_data[i]);
} }
// if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", check, crc);
if (crc != check)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
} }
//reset the sacch field -- Github Issue #118 //reset the sacch field -- Github Issue #118
@@ -296,10 +296,9 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
else fprintf (stderr, " "); else fprintf (stderr, " ");
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
fprintf (stderr, "PF %d/4", part_of_frame+1);
if (crc != check) if (crc != check)
{ {
fprintf (stderr, " SACCH SF%d", sf);
fprintf (stderr, "%s", KRED); fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)"); fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
@@ -333,17 +332,16 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
NXDN_SACCH_Full_decode (opts, state); NXDN_SACCH_Full_decode (opts, state);
} }
// if (opts->payload == 1) if (opts->payload == 1)
// { {
// fprintf (stderr, "\n"); fprintf (stderr, "\n");
// fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1); fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
// for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
// { {
// fprintf (stderr, "[%02X]", m_data[i]); fprintf (stderr, "[%02X]", m_data[i]);
// } }
// // if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check); // if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
// } }
} }
} }
@@ -430,10 +428,15 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
check = check | trellis_buf[i+184]; check = check | trellis_buf[i+184];
} }
fprintf (stderr, "%s", KYEL); if (crc != check)
if (type == 0) fprintf (stderr, " UDCH"); {
if (type == 1) fprintf (stderr, " FACCH2"); fprintf (stderr, "%s", KYEL);
fprintf (stderr, "%s", KNRM); if (type == 0) fprintf (stderr, " UDCH");
if (type == 1) fprintf (stderr, " FACCH2");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
uint8_t f2u_message_buffer[400]; //199 uint8_t f2u_message_buffer[400]; //199
memset (f2u_message_buffer, 0, sizeof(f2u_message_buffer)); memset (f2u_message_buffer, 0, sizeof(f2u_message_buffer));
@@ -467,14 +470,6 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
if (i == 13) fprintf (stderr, "\n "); if (i == 13) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", m_data[i]); fprintf (stderr, "[%02X]", m_data[i]);
} }
if (crc != check)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
// if (crc != check) fprintf (stderr, " CRC ERR "); // if (crc != check) fprintf (stderr, " CRC ERR ");
if (type == 0) if (type == 0)
@@ -729,6 +724,12 @@ void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint
//NOTE: scch has its own message format, and thus, doesn't go to content element decoding //NOTE: scch has its own message format, and thus, doesn't go to content element decoding
//like everything else does //like everything else does
if (crc != check)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
if (crc == check) NXDN_decode_scch (opts, state, trellis_buf, direction); if (crc == check) NXDN_decode_scch (opts, state, trellis_buf, direction);
else if (opts->aggressive_framesync == 0) NXDN_decode_scch (opts, state, trellis_buf, direction); else if (opts->aggressive_framesync == 0) NXDN_decode_scch (opts, state, trellis_buf, direction);
@@ -742,13 +743,7 @@ void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint
{ {
fprintf (stderr, "[%02X]", m_data[i]); fprintf (stderr, "[%02X]", m_data[i]);
} }
// if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", check, crc);
if (crc != check)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
} }
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
@@ -838,11 +833,14 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
for (int i = 0; i < 12; i++) f3_udch2_bytes[i+(j*12)] = m_data[i]; for (int i = 0; i < 12; i++) f3_udch2_bytes[i+(j*12)] = m_data[i];
} }
fprintf (stderr, "%s", KYEL); if (crc[0] != check[0] || crc[1] != check[1])
if (type == 0) fprintf (stderr, " UDCH2"); {
if (type == 1) fprintf (stderr, " FACCH3"); if (type == 0) fprintf (stderr, " UDCH2");
fprintf (stderr, "%s", KNRM); if (type == 1) fprintf (stderr, " FACCH3");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
if (crc[0] == check[0] && crc[1] == check[1]) if (crc[0] == check[0] && crc[1] == check[1])
{ {
@@ -866,17 +864,8 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
if (i == 12) fprintf (stderr, "\n "); if (i == 12) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", f3_udch2_bytes[i]); fprintf (stderr, "[%02X]", f3_udch2_bytes[i]);
} }
// fprintf (stderr, " - %03X %03X", check[0], crc[0]);
if ( (crc[0] != check[0] || crc[1] != check[1]) && opts->payload == 1) // fprintf (stderr, " - %03X %03X", check[1], crc[1]);
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
// fprintf (stderr, " - %03X %03X", check[0], crc[0]);
// fprintf (stderr, " - %03X %03X", check[1], crc[1]);
}
if (type == 0) if (type == 0)
{ {

View File

@@ -15,13 +15,10 @@
void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state) void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
{ {
uint8_t SACCH[400]; //72 uint8_t SACCH[400]; //72
uint8_t sacch_bytes[10];
uint32_t i; uint32_t i;
uint8_t CrcCorrect = 1; uint8_t CrcCorrect = 1;
memset (SACCH, 0, sizeof (SACCH)); memset (SACCH, 0, sizeof (SACCH));
memset (sacch_bytes, 0, sizeof (sacch_bytes));
/* Consider all SACCH CRC parts as correct */ /* Consider all SACCH CRC parts as correct */
CrcCorrect = 1; CrcCorrect = 1;
@@ -44,17 +41,6 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment)); memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
if (opts->payload == 1)
{
fprintf (stderr, "\n");
fprintf (stderr, " Full SACCH Payload ");
for (i = 0; i < 9; i++)
{
sacch_bytes[i] = (uint8_t)ConvertBitIntoBytes(&SACCH[i*8], 8);
fprintf (stderr, "[%02X]", sacch_bytes[i]);
}
}
} /* End NXDN_SACCH_Full_decode() */ } /* End NXDN_SACCH_Full_decode() */
@@ -74,8 +60,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
MessageType |= (ElementsContent[6] & 1) << 1; MessageType |= (ElementsContent[6] & 1) << 1;
MessageType |= (ElementsContent[7] & 1) << 0; MessageType |= (ElementsContent[7] & 1) << 0;
nxdn_message_type (opts, state, MessageType);
/* Save the "F1" and "F2" flags */ /* Save the "F1" and "F2" flags */
state->NxdnElementsContent.F1 = ElementsContent[0]; state->NxdnElementsContent.F1 = ElementsContent[0];
state->NxdnElementsContent.F2 = ElementsContent[1]; state->NxdnElementsContent.F2 = ElementsContent[1];
@@ -144,10 +128,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
NXDN_decode_VCALL(opts, state, ElementsContent); NXDN_decode_VCALL(opts, state, ElementsContent);
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment)); memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
#ifdef LIMAZULUTWEAKS
; //do nothing -- testing errors on CAC messages when returning quickly from RTCH
#else
//tune back to CC here - save about 1-2 seconds //tune back to CC here - save about 1-2 seconds
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
{ {
@@ -163,23 +143,18 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq); SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR
//extra safeguards due to sync issues with NXDN //extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment)); memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
memset(state->active_channel, 0, sizeof(state->active_channel)); memset(state->active_channel, 0, sizeof(state->active_channel));
opts->p25_is_tuned = 0; opts->p25_is_tuned = 0;
rtl_dev_tune (opts, state->p25_cc_freq); rtl_udp_tune (opts, state, state->p25_cc_freq);
#endif
} }
state->last_cc_sync_time = time(NULL); //allow tuners a second to catch up, particularly rtl input
} }
#endif
break; break;
//Idle //Idle
@@ -198,6 +173,8 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
} }
} /* End switch(MessageType) */ } /* End switch(MessageType) */
nxdn_message_type (opts, state, MessageType);
} /* End NXDN_Elements_Content_decode() */ } /* End NXDN_Elements_Content_decode() */
//externalize multiple sub-element handlers //externalize multiple sub-element handlers
@@ -593,10 +570,9 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
} }
if (state->M == 1) state->nxdn_cipher_type = 0x1; if (state->M == 1) state->nxdn_cipher_type = 0x1;
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR
//extra safeguards due to sync issues with NXDN //extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment)); memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
@@ -605,7 +581,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
// //
rtl_dev_tune (opts, freq); rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
@@ -623,7 +599,6 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
fprintf (stderr, " Key Loaded: %lld", state->rkey_array[DestinationID]); fprintf (stderr, " Key Loaded: %lld", state->rkey_array[DestinationID]);
} }
if (state->M == 1) state->nxdn_cipher_type = 0x1; if (state->M == 1) state->nxdn_cipher_type = 0x1;
#endif
} }
} }
@@ -816,7 +791,7 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
//poll for current frequency, will always be the control channel //poll for current frequency, will always be the control channel
//this PDU is constantly pumped out on the CC CAC Message //this PDU is constantly pumped out on the CC CAC Message
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 0) //changed this so the rtl tuning lag doesn't set RTCH frequency after tuning but before landing if (opts->p25_trunk == 1)
{ {
long int ccfreq = 0; long int ccfreq = 0;
//if using rigctl, we can poll for the current frequency //if using rigctl, we can poll for the current frequency
@@ -826,7 +801,7 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
if (ccfreq != 0) state->p25_cc_freq = ccfreq; if (ccfreq != 0) state->p25_cc_freq = ccfreq;
} }
//if using rtl input, we can ask for the current frequency tuned //if using rtl input, we can ask for the current frequency tuned
else if (opts->audio_in_type == 3) //after changing to rtl_dev_tune, this may lag a bit due to delay in sample delivery? else if (opts->audio_in_type == 3)
{ {
ccfreq = (long int)opts->rtlsdr_center_freq; ccfreq = (long int)opts->rtlsdr_center_freq;
if (ccfreq != 0) state->p25_cc_freq = ccfreq; if (ccfreq != 0) state->p25_cc_freq = ccfreq;
@@ -1150,9 +1125,56 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID]; if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID];
else if (state->rkey_array[DestinationID] != 0) state->R = state->rkey_array[DestinationID]; else if (state->rkey_array[DestinationID] != 0) state->R = state->rkey_array[DestinationID];
// #ifdef LIMAZULUTWEAKS
// //LimaZulu specific tweak, load keys from frequency value, if avalable -- untested
// long int freq = 0;
// uint8_t hash_bits[24];
// memset (hash_bits, 0, sizeof(hash_bits));
// uint16_t limazulu = 0;
// //if not available, then poll rigctl if its available
// if (opts->use_rigctl == 1)
// freq = GetCurrentFreq (opts->rigctl_sockfd);
// //if using rtl input, we can ask for the current frequency tuned
// else if (opts->audio_in_type == 3)
// freq = (long int)opts->rtlsdr_center_freq;
// //freq = 167831250; //hardset for testing
// //since a frequency value will be larger than the 16-bit max, we need to hash it first
// //the hash has to be run the same way as the import, so at a 24-bit depth, which hopefully
// //will not lead to any duplicate key loads due to multiple CRC16 collisions on a larger value?
// for (int i = 0; i < 24; i++)
// hash_bits[i] = ((freq << i) & 0x800000) >> 23; //load into array for CRC16
// if (freq) limazulu = ComputeCrcCCITT16d (hash_bits, 24);
// limazulu = limazulu & 0xFFFF; //make sure no larger than 16-bits
// fprintf (stderr, "%s", KCYN);
// if (freq) fprintf (stderr, "\n Freq: %ld - Freq Hash: %d", freq, limazulu);
// if (state->rkey_array[limazulu] != 0) fprintf (stderr, " - Key Loaded: %lld", state->rkey_array[limazulu]);
// fprintf (stderr, "%s", KNRM);
// if (state->rkey_array[limazulu] != 0)
// state->R = state->rkey_array[limazulu];
// #endif //end LIMAZULUTWEAKS
//Don't zero key if no keyloader //Don't zero key if no keyloader
if (CipherType != 0x1 && state->keyloader == 1) state->R = 0; if (CipherType != 0x1 && state->keyloader == 1) state->R = 0;
//NOTE: Broadcast Call appears to have values that aren't typical for VCALL,
//so not applying any settings below if CallType == 0 (BC Call)
//NOTE: Above note may be in error; its possible that the issues I was having
//was from not resetting the entire SACCH superframe after reading it, and
//the samples in question having interwoven ALIAS and VCALL, and bad settings
//coming from a missed SF Part of Frame, if not reset, we could skip a SF POF
//and still believe we have a good decode -- will need further testing #118
/* Print the "Cipher Type" */ /* Print the "Cipher Type" */
if(CipherType != 0 && MessageType == 0x1) if(CipherType != 0 && MessageType == 0x1)
{ {
@@ -1281,7 +1303,6 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (opcode == 0x4 || opcode == 0x0) //INFO 4 if (opcode == 0x4 || opcode == 0x0) //INFO 4
{ {
//clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?) //clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?)
//may not be entirely necessary here in this context
if ( (time(NULL) - state->last_active_time) > 3 ) if ( (time(NULL) - state->last_active_time) > 3 )
{ {
memset (state->active_channel, 0, sizeof(state->active_channel)); memset (state->active_channel, 0, sizeof(state->active_channel));
@@ -1362,8 +1383,8 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
//add current active to display string -- may need tweaking on if to use rep1 (active ch), or rep2 (home prefix) //add current active to display string -- may need tweaking on if to use rep1 (active ch), or rep2 (home prefix)
if (rep1 != 0 && rep1 != 31) if (rep1 != 0 && rep1 != 31)
{ {
if (gu == 0) sprintf (state->active_channel[rep1], "Active Group Ch: %d TG: %d-%d; ", rep1, rep2, id); //Group TG if (gu == 0) sprintf (state->active_channel[rep1], "Active Ch: %d TG: %d-%d; ", rep1, rep2, id); //Group TG
else sprintf (state->active_channel[rep1], "Active Private Ch: %d TGT: %d-%d; ", rep1, rep2, id); //Private TGT else sprintf (state->active_channel[rep1], "Active Ch: %d TGT: %d-%d; ", rep1, rep2, id); //Private TGT
state->last_active_time = time(NULL); state->last_active_time = time(NULL);
} }
@@ -1409,8 +1430,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
//check to see if the source/target candidate is blocked first //check to see if the source/target candidate is blocked first
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block
{ {
//will need to monitor, 1 second may be too long on idas, may need to try 0 or manipulate another way if (state->p25_cc_freq != 0 && state->last_vc_sync_time > 1 && freq != 0) //if we aren't already on a VC and have a valid frequency already
if (state->p25_cc_freq != 0 && ((time(NULL) - state->last_vc_sync_time) > 1) && freq != 0)
{ {
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
@@ -1431,10 +1451,9 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (state->rkey_array[id] != 0) state->R = state->rkey_array[id]; if (state->rkey_array[id] != 0) state->R = state->rkey_array[id];
if (state->M == 1) state->nxdn_cipher_type = 0x1; if (state->M == 1) state->nxdn_cipher_type = 0x1;
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR
//extra safeguards due to sync issues with NXDN //extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment)); memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
@@ -1442,14 +1461,13 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
state->last_cc_sync_time = time(NULL); state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL); //should we use this here, or not? state->last_vc_sync_time = time(NULL); //should we use this here, or not?
// //
rtl_dev_tune (opts, freq); rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
//check the rkey array for a scrambler key value //check the rkey array for a scrambler key value
//TGT ID and Key ID could clash though if csv or system has both with different keys //TGT ID and Key ID could clash though if csv or system has both with different keys
if (state->rkey_array[id] != 0) state->R = state->rkey_array[id]; if (state->rkey_array[id] != 0) state->R = state->rkey_array[id];
if (state->M == 1) state->nxdn_cipher_type = 0x1; if (state->M == 1) state->nxdn_cipher_type = 0x1;
#endif
} }
} }

View File

@@ -64,7 +64,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
uint8_t facch_bits_b[144]; uint8_t facch_bits_b[144];
uint8_t cac_bits[300]; uint8_t cac_bits[300];
uint8_t facch2_bits[348]; //facch2 or udch, same amount of bits uint8_t facch2_bits[348]; //facch2 or udch, same amount of bits
uint8_t facch3_bits[288]; //facch3 or udch2, same amount of bits uint8_t facch3_bits[288]; //facch3 or udch2, same amoount of bits
//nxdn bit buffer, for easy assignment handling //nxdn bit buffer, for easy assignment handling
int nxdn_bit_buffer[364]; int nxdn_bit_buffer[364];
@@ -252,7 +252,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
if (opts->payload == 1) if (opts->payload == 1)
fprintf (stderr, "L%02X - ", lich); fprintf (stderr, "L%02X - ", lich);
} }
else if (voice || facch || sacch || facch2 || udch || cac) else if (voice || facch || sacch || facch2 || cac)
{ {
if (opts->frame_nxdn48 == 1) if (opts->frame_nxdn48 == 1)
{ {
@@ -396,9 +396,6 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
#endif //end LIMAZULUTWEAKS #endif //end LIMAZULUTWEAKS
if (opts->scanner_mode == 1)
state->last_cc_sync_time = time(NULL) + 2; //add a little extra hangtime between resuming scan
//Option/Steal Flags echoed in Voice, V+F, or Data //Option/Steal Flags echoed in Voice, V+F, or Data
if (voice && !facch) //voice only, no facch steal if (voice && !facch) //voice only, no facch steal
{ {
@@ -464,18 +461,9 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits, 1); if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits, 1);
//SHOULD be okay to run facch1's again on steal frames, will need testing //SHOULD be okay to run facch1's again on steal frames, will need testing
// if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
// if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
//only run facch in second slot if its not equal to the first one
//ideally, this would work better AFTER decoding/FEC
if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a); if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
if (facch & 2) if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
{
if (memcmp (facch_bits_a, facch_bits_b, 144) != 0)
nxdn_deperm_facch(opts, state, facch_bits_b);
}
if (voice) if (voice)
{ {
//restore MBE file open here //restore MBE file open here
@@ -500,7 +488,6 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
closeMbeOutFile (opts, state); closeMbeOutFile (opts, state);
} }
} }
//may need to reconsider this, due to double FACCH1 steals on some Type-C (ASSGN_DUP, etc) and Conventional Systems (random IDLE FACCH1 steal for no reason)
if (opts->frame_nxdn48 == 1) closeMbeOutFile (opts, state); //okay to close right away if nxdn48, no data/voice frames mixing if (opts->frame_nxdn48 == 1) closeMbeOutFile (opts, state); //okay to close right away if nxdn48, no data/voice frames mixing
} }
} }

View File

@@ -295,20 +295,9 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
//tune back to CC here - save about 1-2 seconds //tune back to CC here - save about 1-2 seconds
else if (lc_format == 0x4F) //# Call Termination/Cancellation else if (lc_format == 0x4F) //# Call Termination/Cancellation
{ {
fprintf (stderr, " Call Termination"); fprintf (stderr, " Call Termination/Cancellation");
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
{ {
//Will we need to check for a symbolrate change here, can a P25p2 TDMA-CC system
//revert back to a phase 1 traffic channel or carry a phase 1 traffic channel?
//clear heuristics from current traffic channel
if (opts->frame_p25p1 == 1 && opts->use_heuristics == 1)
{
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
}
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
{ {
@@ -327,10 +316,9 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq); SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR
state->lasttg = 0; state->lasttg = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->payload_algid = 0; state->payload_algid = 0;
@@ -343,8 +331,7 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
sprintf (state->active_channel[1], "%s", ""); sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0; opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0; state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
rtl_dev_tune (opts, state->p25_cc_freq); rtl_udp_tune (opts, state, state->p25_cc_freq);
#endif
} }
} }
} }

View File

@@ -459,9 +459,6 @@ processHDU(dsd_opts* opts, dsd_state* state)
mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32); mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32);
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8); mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
//reset dropbytes - skip first 11 for LCW
state->dropL = 267;
//set vc counter to 0 //set vc counter to 0
state->p25vc = 0; state->p25vc = 0;
@@ -469,24 +466,14 @@ processHDU(dsd_opts* opts, dsd_state* state)
{ {
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2); fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
fprintf (stderr, "%s", KNRM);
state->payload_algid = algidhex; state->payload_algid = algidhex;
state->payload_keyid = kidhex; state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA)
{
fprintf (stderr, " Key: %010llX", state->R);
opts->unmute_encrypted_p25 = 1;
}
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
{
//may want to mute this again, or may not want to
opts->unmute_encrypted_p25 = 0;
}
fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3 //only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2); state->payload_miP = (mihex1 << 32) | (mihex2);
if (state->payload_algid != 0x80 && state->payload_algid != 0x0) if (state->payload_algid != 0x80 && state->payload_algid != 0x0) //print on payload == 1
{ {
fprintf (stderr, "%s", KRED); fprintf (stderr, "%s", KRED);
fprintf (stderr, " ENC"); fprintf (stderr, " ENC");

View File

@@ -171,8 +171,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
// TODO: error correction of the LSD bytes... // TODO: error correction of the LSD bytes...
// TODO: do something useful with the LSD bytes... // TODO: do something useful with the LSD bytes...
state->dropL += 2; //need to skip 2 here for the LSD bytes
} }
// IMBE 9 // IMBE 9

View File

@@ -172,8 +172,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
// TODO: error correction of the LSD bytes... // TODO: error correction of the LSD bytes...
// TODO: do something useful with the LSD bytes... // TODO: do something useful with the LSD bytes...
state->dropL += 2; //need to skip 2 here for the LSD bytes
} }
// IMBE 9 // IMBE 9
@@ -185,9 +183,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
//set vc counter to 0 //set vc counter to 0
state->p25vc = 0; state->p25vc = 0;
//reset dropbytes -- skip first 11 for next LCW
state->dropL = 267;
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
fprintf (stderr, "\n"); fprintf (stderr, "\n");
@@ -371,24 +366,15 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
if (irrecoverable_errors == 0) if (irrecoverable_errors == 0)
{ {
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2); fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
fprintf (stderr, "%s", KNRM);
state->payload_algid = algidhex; state->payload_algid = algidhex;
state->payload_keyid = kidhex; state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA)
{
fprintf (stderr, " Key: %010llX", state->R);
opts->unmute_encrypted_p25 = 1;
}
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
{
//may want to mute this again, or may not want to
opts->unmute_encrypted_p25 = 0;
}
fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3 //only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2); state->payload_miP = (mihex1 << 32) | (mihex2);
if (state->payload_algid != 0x80 && state->payload_algid != 0x0) if (state->payload_algid != 0x80 && state->payload_algid != 0x0) //print on payload == 1
{ {
fprintf (stderr, "%s", KRED); fprintf (stderr, "%s", KRED);
fprintf (stderr, " ENC"); fprintf (stderr, " ENC");
@@ -404,45 +390,4 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
} }
//run LFSR on the MI if we have irrecoverable errors here
if (irrecoverable_errors && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->payload_miP != 0)
{
LFSRP(state);
fprintf (stderr, "\n");
}
}
//LFSR code courtesy of https://github.com/mattames/LFSR/
void LFSRP(dsd_state * state)
{
//rework for P2 TDMA support
unsigned long long int lfsr = 0;
if (state->currentslot == 0)
lfsr = state->payload_miP;
if (state->currentslot == 1)
lfsr = state->payload_miN;
int cnt = 0;
for(cnt=0;cnt<64;cnt++)
{
// Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1
unsigned long long int bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1;
lfsr = (lfsr << 1) | (bit);
}
if (state->currentslot == 0)
state->payload_miP = lfsr;
if (state->currentslot == 1)
state->payload_miN = lfsr;
//print current ENC identifiers already known and new calculated MI
fprintf (stderr, "%s", KYEL);
if (state->currentslot == 0)
fprintf (stderr, " LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algid, state->payload_keyid, state->payload_miP);
if (state->currentslot == 1)
fprintf (stderr, " LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algidR, state->payload_keyidR, state->payload_miN);
fprintf (stderr, "%s", KNRM);
} }

View File

@@ -337,24 +337,14 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency
{ {
//testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
// if (opts->mod_qpsk == 1) if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channelt >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{ {
if (state->p25_chan_tdma[channelt >> 12] == 1) int spacing = state->p25_chan_spac[channelt >> 12];
if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
{ {
state->samplesPerSymbol = 8; state->samplesPerSymbol = 8;
state->symbolCenter = 3; state->symbolCenter = 3;
} }
} }
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
@@ -365,15 +355,13 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq1);
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -433,26 +421,15 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency
{ {
//testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
// if (opts->mod_qpsk == 1) if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channelt >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{ {
if (state->p25_chan_tdma[channelt >> 12] == 1) int spacing = state->p25_chan_spac[channelt >> 12];
if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
{ {
state->samplesPerSymbol = 8; state->samplesPerSymbol = 8;
state->symbolCenter = 3; state->symbolCenter = 3;
} }
} }
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
@@ -463,15 +440,13 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq1);
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }

View File

@@ -475,16 +475,6 @@ void process_4V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 21 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#endif
processMbeFrame (opts, state, NULL, ambe_fr1, NULL); processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL); processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL); processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
@@ -552,7 +542,6 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algid); fprintf (stderr, " ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP); fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf (stderr, " ESSB"); fprintf (stderr, " ESSB");
} }
@@ -568,7 +557,6 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR); fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN); fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf (stderr, " ESSB"); fprintf (stderr, " ESSB");
} }
@@ -576,11 +564,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
} }
if (ec == -1 || ec >= 15) if (ec == -1 || ec >= 15)
{ {
//ESS R-S Failure -- run LFSR on current MI if applicable //ESS R-S Failure
if (state->currentslot == 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->payload_miP != 0)
LFSRP(state);
if (state->currentslot == 1 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->payload_miN != 0)
LFSRP(state);
} }
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
@@ -642,28 +626,11 @@ void process_2V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 21 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#endif
processMbeFrame (opts, state, NULL, ambe_fr1, NULL); processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL); processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
process_ESS(opts, state); process_ESS(opts, state);
//reset drop bytes after a 2V
if (state->currentslot == 0 && state->payload_algid == 0xAA)
state->dropL = 256;
if (state->currentslot == 1 && state->payload_algidR == 0xAA)
state->dropR = 256;
} }
//P2 Data Unit ID //P2 Data Unit ID
@@ -864,7 +831,7 @@ void processP2 (dsd_opts * opts, dsd_state * state)
p2_dibit_buffer (opts, state); p2_dibit_buffer (opts, state);
//look at our ISCH values and determine location in superframe before running frame scramble //look at our ISCH values and determine location in superframe before running frame scramble
for (framing_counter = 0; framing_counter < 4; framing_counter++) for (framing_counter = 0; framing_counter < 4; framing_counter++)
{ {
//run ISCH in here so we know when to start descramble offset //run ISCH in here so we know when to start descramble offset
process_ISCH (opts, state); process_ISCH (opts, state);
@@ -883,7 +850,6 @@ void processP2 (dsd_opts * opts, dsd_state * state)
//process DUID will run through all collected frames and handle them appropriately //process DUID will run through all collected frames and handle them appropriately
process_P2_DUID (opts, state); process_P2_DUID (opts, state);
state->dmr_stereo = 0; state->dmr_stereo = 0;
state->p2_is_lcch = 0; state->p2_is_lcch = 0;
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }

View File

@@ -118,8 +118,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK // //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channel >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[channel >> 12] == 1) if (state->p25_chan_tdma[channel >> 12] == 1)
{ {
@@ -137,15 +148,13 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -194,8 +203,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channel >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[channel >> 12] == 1) if (state->p25_chan_tdma[channel >> 12] == 1)
{ {
@@ -212,15 +232,13 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -302,8 +320,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[tunable_chan >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[tunable_chan >> 12] == 1) if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{ {
@@ -324,16 +353,14 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
j = 8; //break loop j = 8; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, tunable_freq);
rtl_dev_tune (opts, tunable_freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
#endif
} }
} }
} }
@@ -404,8 +431,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channel >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[channel >> 12] == 1) if (state->p25_chan_tdma[channel >> 12] == 1)
{ {
@@ -423,15 +461,13 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -488,8 +524,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channel >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[channel >> 12] == 1) if (state->p25_chan_tdma[channel >> 12] == 1)
{ {
@@ -507,15 +554,13 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -635,8 +680,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[tunable_chan >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[tunable_chan >> 12] == 1) if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{ {
@@ -654,16 +710,14 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, tunable_freq);
rtl_dev_tune (opts, tunable_freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
#endif
} }
} }
} }
@@ -803,8 +857,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[tunable_chan >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[tunable_chan >> 12] == 1) if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{ {
@@ -824,17 +889,15 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, tunable_freq);
rtl_dev_tune (opts, tunable_freq);
//probably best to only set these when really tuning //probably best to only set these when really tuning
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
#endif
} }
} }
} }
@@ -916,8 +979,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already
{ {
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
if (1 == 1) // if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[tunable_chan >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[tunable_chan >> 12] == 1) if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{ {
@@ -937,17 +1011,15 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, tunable_freq);
rtl_dev_tune (opts, tunable_freq);
//probably best to only set these when really tuning //probably best to only set these when really tuning
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
j = 8; //break loop j = 8; //break loop
#endif
} }
} }
} }
@@ -1020,9 +1092,19 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot
if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency
{ {
//testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel
// if (opts->mod_qpsk == 1)
// {
// int spacing = state->p25_chan_spac[channelt >> 12];
// if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
// {
// state->samplesPerSymbol = 8;
// state->symbolCenter = 3;
// }
// }
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK //may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (1 == 1) if (opts->mod_qpsk == 1)
{ {
if (state->p25_chan_tdma[channelt >> 12] == 1) if (state->p25_chan_tdma[channelt >> 12] == 1)
{ {
@@ -1040,15 +1122,13 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
} }
//rtl //rtl_udp
else if (opts->audio_in_type == 3) else if (opts->audio_in_type == 3)
{ {
#ifdef USE_RTLSDR rtl_udp_tune (opts, state, freq1);
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
#endif
} }
} }
} }
@@ -1543,7 +1623,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
int lcolorcode = ((MAC[12+len_a] & 0xF) << 8) | MAC[13+len_a]; int lcolorcode = ((MAC[12+len_a] & 0xF) << 8) | MAC[13+len_a];
fprintf (stderr, "\n Network Status Broadcast - Extended \n"); fprintf (stderr, "\n Network Status Broadcast - Extended \n");
fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X] CHAN-R [%04X]", lra, lwacn, lsysid, lcolorcode, channelt, channelr); fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X] CHAN-R [%04X]", lra, lwacn, lsysid, lcolorcode, channelt, channelr);
state->p25_cc_freq = process_channel_to_freq (opts, state, channelt); process_channel_to_freq (opts, state, channelt);
process_channel_to_freq (opts, state, channelr); process_channel_to_freq (opts, state, channelr);
state->p25_cc_is_tdma = 1; //flag on for CC tuning purposes when system is qpsk state->p25_cc_is_tdma = 1; //flag on for CC tuning purposes when system is qpsk
if (state->p2_hardset == 0 ) //state->p2_is_lcch == 1 shim until CRC is working, prevent bogus data if (state->p2_hardset == 0 ) //state->p2_is_lcch == 1 shim until CRC is working, prevent bogus data

View File

@@ -120,7 +120,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{ {
//reset fourv_counter and dropbyte on PTT //reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0; state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20; state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - "); fprintf (stderr, "\n VCH 0 - ");
@@ -143,7 +142,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid); fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP); fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf(stderr, " MPTT"); fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED); // fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC"); // fprintf (stderr, "ENC");
@@ -155,7 +153,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{ {
//reset fourv_counter and dropbyte on PTT //reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0; state->fourv_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well state->payload_algidR = 0; //zero this out as well
state->dmrburstR = 20; state->dmrburstR = 20;
@@ -179,7 +176,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR); fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN); fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf(stderr, " MPTT"); fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED); // fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC"); // fprintf (stderr, "ENC");
@@ -198,7 +194,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{ {
state->fourv_counter[0] = 0; state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23; state->dmrburstL = 23;
state->payload_algid = 0; state->payload_algid = 0;
state->payload_keyid = 0; state->payload_keyid = 0;
@@ -222,7 +217,6 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{ {
state->fourv_counter[1] = 0; state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23; state->dmrburstR = 23;
state->payload_algidR = 0; state->payload_algidR = 0;
state->payload_keyidR = 0; state->payload_keyidR = 0;
@@ -251,22 +245,11 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
//blank the call string here -- slot variable is already flipped accordingly for sacch //blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces sprintf (state->call_string[slot], "%s", " "); //21 spaces
} }
if (opcode == 0x4 && err == 0) if (opcode == 0x4 && err == 0)
{ {
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
#ifdef AERO_BUILD
if (opts->audio_out_type != 5)
{
if (state->currentslot == 1) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#else
if (state->currentslot == 1) state->dmrburstL = 21; if (state->currentslot == 1) state->dmrburstL = 21;
else state->dmrburstR = 21; else state->dmrburstR = 21;
#endif
fprintf (stderr, " MAC_ACTIVE "); fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC); process_MAC_VPDU(opts, state, 1, SMAC);
@@ -276,13 +259,13 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{ {
if (state->currentslot == 1) if (state->currentslot == 1)
{ {
state->dmrburstL = 22; state->dmrburstL = 21;
//close any open MBEout files //close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
} }
else else
{ {
state->dmrburstR = 22; state->dmrburstR = 21;
//close any open MBEout files //close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state); if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
} }
@@ -375,7 +358,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{ {
//reset fourv_counter and dropbyte on PTT //reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0; state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20; state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - "); fprintf (stderr, "\n VCH 0 - ");
@@ -398,7 +380,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid); fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP); fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf(stderr, " MPTT"); fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED); // fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC"); // fprintf (stderr, "ENC");
@@ -410,7 +391,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{ {
//reset fourv_counter and dropbyte on PTT //reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0; state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20; state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - "); fprintf (stderr, "\n VCH 1 - ");
@@ -433,7 +413,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR); fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN); fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf(stderr, " MPTT"); fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED); // fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC"); // fprintf (stderr, "ENC");
@@ -451,7 +430,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{ {
state->fourv_counter[0] = 0; state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23; state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well state->payload_algid = 0; //zero this out as well
state->payload_keyid = 0; state->payload_keyid = 0;
@@ -475,7 +453,6 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{ {
state->fourv_counter[1] = 0; state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23; state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well state->payload_algidR = 0; //zero this out as well
state->payload_keyidR = 0; state->payload_keyidR = 0;
@@ -521,25 +498,14 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC); process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
//blank the call string here //blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces sprintf (state->call_string[slot], "%s", " "); //21 spaces
} }
if (opcode == 0x4 && err == 0) if (opcode == 0x4 && err == 0)
{ {
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
#ifdef AERO_BUILD
if (opts->audio_out_type != 5)
{
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#else
if (state->currentslot == 0) state->dmrburstL = 21; if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21; else state->dmrburstR = 21;
#endif
fprintf (stderr, " MAC_ACTIVE "); fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC); process_MAC_VPDU(opts, state, 0, FMAC);

View File

@@ -31,12 +31,12 @@
#include <rtl-sdr.h> #include <rtl-sdr.h>
#include "dsd.h" #include "dsd.h"
#define DEFAULT_SAMPLE_RATE 48000 //#define DEFAULT_SAMPLE_RATE 48000 //moved to opts->rtl_bandwidth
#define DEFAULT_BUF_LENGTH (1 * 16384) #define DEFAULT_BUF_LENGTH (1 * 16384)
#define MAXIMUM_OVERSAMPLE 16 #define MAXIMUM_OVERSAMPLE 16 //16
#define MAXIMUM_BUF_LENGTH (MAXIMUM_OVERSAMPLE * DEFAULT_BUF_LENGTH) #define MAXIMUM_BUF_LENGTH (MAXIMUM_OVERSAMPLE * DEFAULT_BUF_LENGTH)
#define AUTO_GAIN -100 #define AUTO_GAIN -100
#define BUFFER_DUMP 4096 #define BUFFER_DUMP 4096
#define FREQUENCIES_LIMIT 1000 #define FREQUENCIES_LIMIT 1000
@@ -46,8 +46,7 @@ static int ACTUAL_BUF_LENGTH;
static int *atan_lut = NULL; static int *atan_lut = NULL;
static int atan_lut_size = 131072; /* 512 KB */ static int atan_lut_size = 131072; /* 512 KB */
static int atan_lut_coef = 8; static int atan_lut_coef = 8;
//new for UDP
//UDP -- keep for compatibility reasons
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
static pthread_t socket_freq; static pthread_t socket_freq;
@@ -58,7 +57,7 @@ int bandwidth_divisor = 48000; //divide bandwidth by this to get multiplier for
short int volume_multiplier; short int volume_multiplier;
short int port; short int port;
//
struct dongle_state struct dongle_state
{ {
int exit_flag; int exit_flag;
@@ -598,6 +597,7 @@ static void *demod_thread_fn(void *arg)
int nearest_gain(rtlsdr_dev_t *dev, int target_gain) int nearest_gain(rtlsdr_dev_t *dev, int target_gain)
{ {
//target_gain = 36;
int i, r, err1, err2, count, nearest; int i, r, err1, err2, count, nearest;
int* gains; int* gains;
r = rtlsdr_set_tuner_gain_mode(dev, 1); r = rtlsdr_set_tuner_gain_mode(dev, 1);
@@ -628,9 +628,10 @@ int verbose_set_frequency(rtlsdr_dev_t *dev, uint32_t frequency)
int r; int r;
r = rtlsdr_set_center_freq(dev, frequency); r = rtlsdr_set_center_freq(dev, frequency);
if (r < 0) { if (r < 0) {
fprintf (stderr, " (WARNING: Failed to set Center Frequency). \n"); fprintf (stderr, "WARNING: Failed to set center freq.\n");
} else { } else {
fprintf (stderr, " (Center Frequency: %u Hz.) \n", frequency); //fprintf (stderr, "Tuned to %u Hz.\n", frequency);
fprintf (stderr, "Tuned to center frequency %u Hz.\n", frequency);
} }
return r; return r;
} }
@@ -678,6 +679,7 @@ int verbose_offset_tuning(rtlsdr_dev_t *dev)
int verbose_auto_gain(rtlsdr_dev_t *dev) int verbose_auto_gain(rtlsdr_dev_t *dev)
{ {
int r; int r;
r = rtlsdr_set_tuner_gain_mode(dev, 0); r = rtlsdr_set_tuner_gain_mode(dev, 0);
if (r != 0) { if (r != 0) {
@@ -690,6 +692,7 @@ int verbose_auto_gain(rtlsdr_dev_t *dev)
int verbose_gain_set(rtlsdr_dev_t *dev, int gain) int verbose_gain_set(rtlsdr_dev_t *dev, int gain)
{ {
//gain = 36;
int r; int r;
r = rtlsdr_set_tuner_gain_mode(dev, 1); r = rtlsdr_set_tuner_gain_mode(dev, 1);
if (r < 0) { if (r < 0) {
@@ -707,6 +710,7 @@ int verbose_gain_set(rtlsdr_dev_t *dev, int gain)
int verbose_ppm_set(rtlsdr_dev_t *dev, int ppm_error) int verbose_ppm_set(rtlsdr_dev_t *dev, int ppm_error)
{ {
//ppm_error = -2; //fix this opt arg to accept negative float values, i.e. float or double??
int r; int r;
if (ppm_error == 0) { if (ppm_error == 0) {
return 0;} return 0;}
@@ -728,23 +732,25 @@ int verbose_reset_buffer(rtlsdr_dev_t *dev)
return r; return r;
} }
static void optimal_settings(int freq, int rate) //static void optimal_settings(struct fm_state *fm, int freq, int hopping)
static void optimal_settings(int freq, int rate) //
{ {
// giant ball of hacks // giant ball of hacks
// seems unable to do a single pass, 2:1 // seems unable to do a single pass, 2:1
//int r, capture_freq, capture_rate;
int capture_freq, capture_rate; int capture_freq, capture_rate;
struct dongle_state *d = &dongle; struct dongle_state *d = &dongle;
struct demod_state *dm = &demod; struct demod_state *dm = &demod;
struct controller_state *cs = &controller; struct controller_state *cs = &controller;
dm->downsample = (1000000 / dm->rate_in) + 1; //dm->rate_in is the rtl_bandwidth value dm->downsample = (1000000 / dm->rate_in) + 1;
if (dm->downsample_passes) { if (dm->downsample_passes) {
dm->downsample_passes = (int)log2(dm->downsample) + 1; dm->downsample_passes = (int)log2(dm->downsample) + 1;
dm->downsample = 1 << dm->downsample_passes; dm->downsample = 1 << dm->downsample_passes;
} }
capture_freq = freq; capture_freq = freq;
capture_rate = dm->downsample * dm->rate_in; // capture_rate = dm->downsample * dm->rate_in;
if (!d->offset_tuning) { if (!d->offset_tuning) {
capture_freq = freq + capture_rate/4;} // capture_freq = freq + capture_rate/4;}
capture_freq += cs->edge * dm->rate_in / 2; capture_freq += cs->edge * dm->rate_in / 2;
dm->output_scale = (1<<15) / (128 * dm->downsample); dm->output_scale = (1<<15) / (128 * dm->downsample);
if (dm->output_scale < 1) { if (dm->output_scale < 1) {
@@ -753,7 +759,6 @@ static void optimal_settings(int freq, int rate)
dm->output_scale = 1;} dm->output_scale = 1;}
d->freq = (uint32_t)capture_freq; d->freq = (uint32_t)capture_freq;
d->rate = (uint32_t)capture_rate; d->rate = (uint32_t)capture_rate;
// fprintf (stderr, "Capture Frequency: %i Rate: %i \n", capture_freq, capture_rate);
} }
static void *controller_thread_fn(void *arg) static void *controller_thread_fn(void *arg)
@@ -785,6 +790,7 @@ static void *controller_thread_fn(void *arg)
/* Set the sample rate */ /* Set the sample rate */
verbose_set_sample_rate(dongle.dev, dongle.rate); verbose_set_sample_rate(dongle.dev, dongle.rate);
fprintf (stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample); fprintf (stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample);
fprintf (stderr, "Press CTRL + C to close.\n");
while (!exitflag) { while (!exitflag) {
safe_cond_wait(&s->hop, &s->hop_m); safe_cond_wait(&s->hop, &s->hop_m);
@@ -801,16 +807,20 @@ static void *controller_thread_fn(void *arg)
void dongle_init(struct dongle_state *s) void dongle_init(struct dongle_state *s)
{ {
//s->rate = DEFAULT_SAMPLE_RATE;
s->rate = rtl_bandwidth; s->rate = rtl_bandwidth;
s->gain = AUTO_GAIN; // tenths of a dB s->gain = AUTO_GAIN; // tenths of a dB
s->mute = 0; s->mute = 0;
s->direct_sampling = 0; s->direct_sampling = 0;
s->offset_tuning = 0; //E4000 tuners only s->offset_tuning = 0; //
s->demod_target = &demod; s->demod_target = &demod;
} }
void demod_init(struct demod_state *s) void demod_init(struct demod_state *s)
{ {
//s->rate_in = DEFAULT_SAMPLE_RATE;
//s->rate_out = DEFAULT_SAMPLE_RATE;
s->rate_in = rtl_bandwidth; s->rate_in = rtl_bandwidth;
s->rate_out = rtl_bandwidth; s->rate_out = rtl_bandwidth;
s->squelch_level = 0; s->squelch_level = 0;
@@ -820,16 +830,16 @@ void demod_init(struct demod_state *s)
s->downsample_passes = 0; s->downsample_passes = 0;
s->comp_fir_size = 0; s->comp_fir_size = 0;
s->prev_index = 0; s->prev_index = 0;
s->post_downsample = 1; //1 -- once this works, default = 4 -- doesn't work on the official rtl-sdr source code either s->post_downsample = 1; // once this works, default = 4
s->custom_atan = 0; s->custom_atan = 0;
s->deemph = 0; s->deemph = 0;
s->rate_out2 = rtl_bandwidth; // -1 flag for disabled -- this enables low_pass_real, seems to work okay s->rate_out2 = -1; // flag for disabled
s->mode_demod = &fm_demod; s->mode_demod = &fm_demod;
s->pre_j = s->pre_r = s->now_r = s->now_j = 0; s->pre_j = s->pre_r = s->now_r = s->now_j = 0;
s->prev_lpr_index = 0; s->prev_lpr_index = 0;
s->deemph_a = 0; s->deemph_a = 0;
s->now_lpr = 0; s->now_lpr = 0;
s->dc_block = 1; //enabling by default, but offset tuning is also enabled, so center spike shouldn't be an issue s->dc_block = 0;
s->dc_avg = 0; s->dc_avg = 0;
pthread_rwlock_init(&s->rw, NULL); pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL); pthread_cond_init(&s->ready, NULL);
@@ -846,6 +856,7 @@ void demod_cleanup(struct demod_state *s)
void output_init(struct output_state *s) void output_init(struct output_state *s)
{ {
//s->rate = DEFAULT_SAMPLE_RATE;
s->rate = rtl_bandwidth; s->rate = rtl_bandwidth;
pthread_rwlock_init(&s->rw, NULL); pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL); pthread_cond_init(&s->ready, NULL);
@@ -893,8 +904,7 @@ void sanity_checks(void)
} }
} }
//UDP remote all below HERE
//UDP remote stuff
static unsigned int chars_to_int(unsigned char* buf) { static unsigned int chars_to_int(unsigned char* buf) {
int i; int i;
@@ -908,7 +918,9 @@ static unsigned int chars_to_int(unsigned char* buf) {
} }
static void *socket_thread_fn(void *arg) { static void *socket_thread_fn(void *arg) {
//struct fm_state *fm = arg;
struct demod_state *d = static_cast<demod_state*>(arg); struct demod_state *d = static_cast<demod_state*>(arg);
//int port = 6020;
int r, n; int r, n;
int sockfd, newsockfd, portno; int sockfd, newsockfd, portno;
socklen_t clilen; socklen_t clilen;
@@ -940,34 +952,114 @@ static void *socket_thread_fn(void *arg) {
while((n = read(sockfd,buffer,5)) != 0) { while((n = read(sockfd,buffer,5)) != 0) {
if(buffer[0] == 0) { if(buffer[0] == 0) {
new_freq = chars_to_int(buffer); new_freq = chars_to_int(buffer);
dongle.freq = new_freq; dongle.freq = new_freq; //
//opts->rtlsdr_center_freq = new_freq; //or dongle.freq, this should update the freq displayed in ncurses terminal hopefully and not do anything naughty
optimal_settings(new_freq, demod.rate_in); optimal_settings(new_freq, demod.rate_in);
rtlsdr_set_center_freq(dongle.dev, dongle.freq); rtlsdr_set_center_freq(dongle.dev, dongle.freq);
//verbose_set_frequency (dongle.dev, new_freq);
//fprintf (stderr, "Tuning to: %d [Hz] (central freq: %d [Hz])\n", new_freq, new_freq + freq_offset);
fprintf (stderr, "\nTuning to: %d [Hz] \n", new_freq); fprintf (stderr, "\nTuning to: %d [Hz] \n", new_freq);
} }
/*
if(buffer[0] == 1) {
// change demod type
int type = chars_to_int(buffer);
switch(type) {
case 0:
fprintf (stderr, "Changing demod type to FM\n");
fm->mode_demod = &fm_demod;
break;
case 1:
fprintf (stderr, "Changing demod type to AM\n");
fm->mode_demod = &am_demod;
break;
case 2:
fprintf (stderr, "Changing demod type to USB\n");
fm->mode_demod = &usb_demod;
fm->custom_atan = 1;
break;
case 3:
fprintf (stderr, "Changing demod type to LSB\n");
fm->mode_demod = &lsb_demod;
break;
default:
fprintf (stderr, "Unknown demod type %d\n", type);
break;
}
}
*/
//SQUELCH HERE
if (buffer[0] == 2) {
new_squelch = chars_to_int(buffer);
demod.squelch_level = new_squelch; //demod, or d*? or d->
//full_demod(d);
//new_freq = 850000000;
//dongle.freq = new_freq;
//optimal_settings(new_freq, demod.rate_in); //hacky way to 'squelch', just setting it to a dead freq instead
//rtlsdr_set_center_freq(dongle.dev, dongle.freq);
fprintf (stderr, "Changing squelch to %d \n", new_squelch);
}
/*
if (buffer[0] == 3) {
new_gain = chars_to_int(buffer);
if (new_gain == AUTO_GAIN) {
r = rtlsdr_set_tuner_gain_mode(dev, 0);
} else {
r = rtlsdr_set_tuner_gain_mode(dev, 1);
new_gain = nearest_gain(new_gain);
r = rtlsdr_set_tuner_gain(dev, new_gain);
}
if (r != 0) {
fprintf (stderr, "WARNING: Failed to set tuner gain.\n");
} else if (new_gain == AUTO_GAIN) {
fprintf (stderr, "Tuner gain set to automatic.\n");
} else {
fprintf (stderr, "Tuner gain set to %0.2f dB.\n", new_gain/10.0);
}
}
*/
/*
if (buffer[0] == 8) {
agc_mode = chars_to_int(buffer);
if (agc_mode == 0 || agc_mode == 1) {
fprintf (stderr, "Setting AGC to %d\n", agc_mode);
rtlsdr_set_agc_mode(dev, agc_mode);
} else {
fprintf (stderr, "Failed to set AGC to %d\n", agc_mode);
}
}
*/
} }
close(sockfd); close(sockfd);
return 0; return 0;
} }
//UDP stuff end //UDP Control all above HERE
void rtlsdr_sighandler() void rtlsdr_sighandler()
{ {
fprintf (stderr, "Signal caught, exiting!\n"); //fprintf (stderr, "Signal caught, exiting!\n");
//fprintf (stderr, "Press CTRL + C again to close. Thanks. \n"); //Kindly remind user to double tap CTRL + C
rtlsdr_cancel_async(dongle.dev); rtlsdr_cancel_async(dongle.dev);
//cleanup_rtlsdr_stream(); //thank the wraith for this one...if it works...didn't work
//_Exit(1);
} }
void open_rtlsdr_stream(dsd_opts *opts) void open_rtlsdr_stream(dsd_opts *opts)
{ {
struct sigaction sigact; struct sigaction sigact;
int r; int r;
rtl_bandwidth = opts->rtl_bandwidth * 1000; //reverted back to straight value rtl_bandwidth = opts->rtl_bandwidth * 1000; //multiple by 1000 to get rate
//rtl_bandwidth = 48000;
bandwidth_multiplier = (bandwidth_divisor / rtl_bandwidth); bandwidth_multiplier = (bandwidth_divisor / rtl_bandwidth);
//bandwidth_multiplier = 1;
//this needs to be initted first, then we set the parameters
dongle_init(&dongle); dongle_init(&dongle);
demod_init(&demod); demod_init(&demod);
output_init(&output); output_init(&output);
@@ -978,23 +1070,29 @@ void open_rtlsdr_stream(dsd_opts *opts)
controller.freq_len++; controller.freq_len++;
} }
if (opts->rtlsdr_ppm_error != 0) { if (opts->rtlsdr_ppm_error > 0 || opts->rtlsdr_ppm_error < 0) { //this way will adjust PPM based on negative values as well
dongle.ppm_error = opts->rtlsdr_ppm_error; dongle.ppm_error = opts->rtlsdr_ppm_error;
fprintf (stderr, "Setting RTL PPM Error Set to %d\n", opts->rtlsdr_ppm_error); fprintf (stderr, "Setting RTL PPM Error Set to %d\n", opts->rtlsdr_ppm_error);
} }
dongle.dev_index = opts->rtl_dev_index; if (opts->audio_in_type == 3) {
// demod.squelch_level = opts->rtl_squelch_level; //no longer used here, used in framesync vc rms value under select conditions dongle.dev_index = opts->rtl_dev_index;
fprintf (stderr, "Setting RTL Bandwidth to %d Hz\n", rtl_bandwidth); //rtl_bandwidth = opts->rtl_bandwidth * 1000; //multiple by 1000 to get rate
// fprintf (stderr, "Setting RTL Sample Multiplier to %d\n", bandwidth_multiplier); //rtl_bandwidth = 48000;
fprintf (stderr, "Setting RTL RMS Squelch Level to %d\n", opts->rtl_squelch_level); //bandwidth_multiplier = rtl_bandwidth / bandwidth_divisor; //find multiple with no remainder if oddball number entered
if (opts->rtl_udp_port != 0) port = opts->rtl_udp_port; //set this here, only open socket thread if set //bandwidth_multiplier = 1;
demod.squelch_level = opts->rtl_squelch_level; //adding user definable squelch level to prevent false positives on account of noise in NXDN etc
fprintf (stderr, "Setting RTL VFO Bandwidth to %d Hz\n", rtl_bandwidth);
fprintf (stderr, "Setting RTL Sample Multiplier to %d\n", bandwidth_multiplier);
fprintf (stderr, "Setting RTL Squelch Level to %d\n", demod.squelch_level);
port = opts->rtl_udp_port;
}
if (opts->rtl_gain_value > 0) { if (opts->rtl_gain_value > 0) {
dongle.gain = opts->rtl_gain_value * 10; //multiple by ten to make it consitent with the way rtl_fm works dongle.gain = opts->rtl_gain_value * 10; //multiple by ten to make it consitent with the way rtl_fm really works
} }
volume_multiplier = opts->rtl_volume_multiplier; volume_multiplier = opts->rtl_volume_multiplier;
// fprintf (stderr, "Setting RTL Volume Multiplier to %d\n", volume_multiplier); fprintf (stderr, "Setting RTL Volume Multiplier to %d\n", volume_multiplier);
/* quadruple sample_rate to limit to Δθ to ±π/2 */ /* quadruple sample_rate to limit to Δθ to ±π/2 */
demod.rate_in *= demod.post_downsample; demod.rate_in *= demod.post_downsample;
@@ -1005,16 +1103,24 @@ void open_rtlsdr_stream(dsd_opts *opts)
if (controller.freq_len > 1) demod.terminate_on_squelch = 0; if (controller.freq_len > 1) demod.terminate_on_squelch = 0;
ACTUAL_BUF_LENGTH = lcm_post[demod.post_downsample] * DEFAULT_BUF_LENGTH; ACTUAL_BUF_LENGTH = lcm_post[demod.post_downsample] * DEFAULT_BUF_LENGTH;
r = rtlsdr_open(&dongle.dev, (uint32_t)dongle.dev_index); r = rtlsdr_open(&dongle.dev, (uint32_t)dongle.dev_index);
if (r < 0) if (r < 0)
{ {
fprintf (stderr, "Failed to open rtlsdr device %d.\n", dongle.dev_index); fprintf (stderr, "Failed to open rtlsdr device %d.\n", dongle.dev_index);
exit(1); exit(1);
} else { } else {
fprintf (stderr, "Using RTLSDR Device Index: %d. \n", dongle.dev_index); fprintf (stderr, "Using RTLSDR Device Index: %d. \n", dongle.dev_index); //Kindly tell us which device we are using
} }
// sigact.sa_handler = sighandler;
// sigemptyset(&sigact.sa_mask);
// sigact.sa_flags = 0;
// sigaction(SIGINT, &sigact, NULL);
// sigaction(SIGTERM, &sigact, NULL);
// sigaction(SIGQUIT, &sigact, NULL);
// sigaction(SIGPIPE, &sigact, NULL);
if (demod.deemph) { if (demod.deemph) {
demod.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(demod.rate_out * 75e-6))))); demod.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(demod.rate_out * 75e-6)))));
} }
@@ -1022,11 +1128,9 @@ void open_rtlsdr_stream(dsd_opts *opts)
/* Set the tuner gain */ /* Set the tuner gain */
if (dongle.gain == AUTO_GAIN) { if (dongle.gain == AUTO_GAIN) {
verbose_auto_gain(dongle.dev); verbose_auto_gain(dongle.dev);
fprintf (stderr, "Setting RTL Autogain. \n");
} else { } else {
dongle.gain = nearest_gain(dongle.dev, dongle.gain); dongle.gain = nearest_gain(dongle.dev, dongle.gain);
verbose_gain_set(dongle.dev, dongle.gain); verbose_gain_set(dongle.dev, dongle.gain);
// fprintf (stderr, "Setting RTL Nearest Gain to %d. \n", dongle.gain); //seems to be working now
} }
verbose_ppm_set(dongle.dev, dongle.ppm_error); verbose_ppm_set(dongle.dev, dongle.ppm_error);
@@ -1038,8 +1142,7 @@ void open_rtlsdr_stream(dsd_opts *opts)
usleep(100000); usleep(100000);
pthread_create(&demod.thread, NULL, demod_thread_fn, (void*)(&demod)); pthread_create(&demod.thread, NULL, demod_thread_fn, (void*)(&demod));
pthread_create(&dongle.thread, NULL, dongle_thread_fn, (void*)(&dongle)); pthread_create(&dongle.thread, NULL, dongle_thread_fn, (void*)(&dongle));
//only create socket thread IF user specified (for legacy uses), else don't use it pthread_create(&socket_freq, NULL, socket_thread_fn, (void *)(&controller));
if (port != 0) pthread_create(&socket_freq, NULL, socket_thread_fn, (void *)(&controller));
} }
void cleanup_rtlsdr_stream() void cleanup_rtlsdr_stream()
@@ -1052,6 +1155,8 @@ void cleanup_rtlsdr_stream()
safe_cond_signal(&output.ready, &output.ready_m); safe_cond_signal(&output.ready, &output.ready_m);
safe_cond_signal(&controller.hop, &controller.hop_m); safe_cond_signal(&controller.hop, &controller.hop_m);
pthread_join(controller.thread, NULL); pthread_join(controller.thread, NULL);
//add socket thread
//pthread_join(socket_freq, NULL);
//dongle_cleanup(&dongle); //dongle_cleanup(&dongle);
demod_cleanup(&demod); demod_cleanup(&demod);
@@ -1059,69 +1164,32 @@ void cleanup_rtlsdr_stream()
controller_cleanup(&controller); controller_cleanup(&controller);
rtlsdr_close(dongle.dev); rtlsdr_close(dongle.dev);
} }
//original for safe keeping //void get_rtlsdr_sample(int16_t *sample)
// void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state)
// {
// if (output.queue.empty())
// {
// safe_cond_wait(&output.ready, &output.ready_m);
// }
// pthread_rwlock_wrlock(&output.rw);
// *sample = output.queue.front() * volume_multiplier;
// output.queue.pop();
// pthread_rwlock_unlock(&output.rw);
// }
//find way to modify this function to allow hopping (tuning) while squelched and send 0 sample?
void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state) void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state)
{ {
if (output.queue.empty()) if (output.queue.empty())
{ {
if (opts->use_ncurses_terminal == 1)
{
//ncursesPrinter(opts, state);
//printw ("\n\n\n HELP I'M LOCKED!\n");
}
safe_cond_wait(&output.ready, &output.ready_m); safe_cond_wait(&output.ready, &output.ready_m);
//goto END;
} }
pthread_rwlock_wrlock(&output.rw); pthread_rwlock_wrlock(&output.rw);
*sample = output.queue.front() * volume_multiplier; //*sample = output.queue.front();
*sample = output.queue.front() * volume_multiplier; //try multiplying by numbers here for 'gain'
output.queue.pop(); output.queue.pop();
pthread_rwlock_unlock(&output.rw); pthread_rwlock_unlock(&output.rw);
// END:
// if (1 == 2)
// {
// fprintf (stderr, "This is a dumb thing to fix");
// }
} }
//function may lag since it isn't running as its own thread
void rtl_dev_tune(dsd_opts * opts, long int frequency)
{
int r;
if (opts->payload == 1)
fprintf (stderr, "\nTuning to %lu Hz.", frequency);
dongle.freq = opts->rtlsdr_center_freq = frequency;
optimal_settings(dongle.freq, demod.rate_in);
if (opts->payload == 1)
fprintf (stderr, " (Center Frequency: %u Hz.) \n", dongle.freq);
r = rtlsdr_set_center_freq(dongle.dev, dongle.freq);
if (r < 0)
fprintf (stderr, " (WARNING: Failed to set Center Frequency %u). \n", dongle.freq);
pthread_rwlock_wrlock(&output.rw); //prevent possible segfault when cleaning the queue
rtl_clean_queue();
pthread_rwlock_unlock(&output.rw); //resume
}
//return RMS value (root means square) power level -- used as soft squelch inside of framesync
int rtl_return_rms()
{
int sr = 0;
sr = rms(demod.lowpassed, demod.lp_len, 1);
// 'Fix' potential negative value overflow from the rms function -- Observed in Windows builds
sr = abs(sr);
if (sr > 9999) sr = 9999;
return (sr);
}
//simple function to clear the rtl sample queue when tuning and during other events (ncurses menu open/close)
void rtl_clean_queue()
{
//insert method to clear the entire queue to prevent sample 'lag'
std::queue<int16_t> empty; //create an empty queue
std::swap( output.queue, empty ); //swap in empty queue to effectively zero out current queue
}

View File

@@ -223,6 +223,7 @@ unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tr
void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits) void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits)
{ {
int n; int n;
signed char dibit;
//can only assume this is giving the correct dibits out, and not inverse or something. //can only assume this is giving the correct dibits out, and not inverse or something.
/* /*
for (int i = 0; i < 98; i++) { for (int i = 0; i < 98; i++) {
@@ -436,15 +437,15 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
} }
} }
unsigned char points[49U]; unsigned char points[49U];
// unsigned char reverse_points[49U]; unsigned char reverse_points[49U];
CDMRTrellisDibitsToPoints(dibits, points); CDMRTrellisDibitsToPoints(dibits, points);
//maybe keep point 49 at 49, since its the flush? //maybe keep point 49 at 49, since its the flush?
//fprintf (stderr, "\n Trellis Reverse Points inside Decoder\n "); //fprintf (stderr, "\n Trellis Reverse Points inside Decoder\n ");
// for (short i = 0; i < 49; i++) for (short i = 0; i < 49; i++)
// { {
// reverse_points[i] = points[48-i]; reverse_points[i] = points[48-i];
// //fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]); //fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]);
// } }
//reverse_points[48] = points[48]; //reverse_points[48] = points[48];
//fprintf (stderr, "#%d [%02u] ", 48, reverse_points[48]); //fprintf (stderr, "#%d [%02u] ", 48, reverse_points[48]);

1305
src/ysf.c

File diff suppressed because it is too large Load Diff