36 Commits

Author SHA1 Message Date
lwvmobile
846b202192 Fix P25p1 -f1 Unmute on RC4 Key; Misc; 2023-06-11 19:43:49 -04:00
lwvmobile
330ebe2bf3 Fix Aero OSS Slot Preemption Issues; #127 2023-06-11 03:09:32 -04:00
lwvmobile
79b4a5e720 Fix DMR LE Alg/Key on SB; 2023-06-11 02:22:41 -04:00
lwvmobile
8186b62a91 RC4 Support (DMR, P25p1, P25p2); 2023-06-11 00:11:55 -04:00
lwvmobile
20f0c852aa NXDN Frame Print Tweaks; #123 2023-06-07 18:27:41 -04:00
lwvmobile
9e4ae23c0b Lit Fix and Tones Fix; #127 2023-06-06 20:32:09 -04:00
lwvmobile
585f6f2fa5 Staging for Main Branch #127 Lit Update; 2023-06-06 20:15:34 -04:00
lwvmobile
a4fba3b19c More Codeset Consolidation #127 Location of tones; 2023-06-06 19:53:30 -04:00
lwvmobile
a2180eb5d3 Switch to New NXDN FS (again) #123 2023-06-06 19:01:37 -04:00
lwvmobile
514161fefa NXDN Frame Tweaks; Late Nite FS Testing III; #123 2023-06-05 23:23:32 -04:00
lwvmobile
bba059f35f Late Nite FS Testing II; #123 2023-06-05 03:29:06 -04:00
lwvmobile
5977f865e3 Remove Min/Max Test (mixed results); #123 2023-06-05 02:43:37 -04:00
lwvmobile
ade7c0477f Late Nite FS Testing; #123 2023-06-05 02:17:38 -04:00
lwvmobile
a2fded8340 Revert Change to new NXDN FS; #123 2023-06-04 20:41:16 -04:00
lwvmobile
005e15c45f cmake remove 'zdev' #127 2023-06-04 18:56:41 -04:00
lwvmobile
e9962a8923 NXDN Switch to New FS; Payload Tweaks; #123 2023-06-04 18:45:05 -04:00
lwvmobile
c6611eae9c Update Some Documentation; 2023-06-03 03:55:43 -04:00
lwvmobile
261193959c Restore Documentation and Examples; 2023-06-02 19:21:25 -04:00
lwvmobile
e7a71eabb6 Minor Fix to Call String; 2023-06-02 16:42:38 -04:00
lwvmobile
afba84e584 Cap+ Call String Blink Fix; Minor Tweaks; #125 2023-05-30 14:52:44 -04:00
lwvmobile
96faff7711 RTL Verbosity Tweaks and Thread Safety; #125 2023-05-24 09:17:50 -04:00
lwvmobile
94166b493c Misc; #123 #125; 2023-05-23 06:21:58 -04:00
lwvmobile
6a0b1b2dcf RTL/NCURSES - Clear Queue and Dibit Buffer; #125 2023-05-21 20:19:56 -04:00
lwvmobile
5c8e3d95a7 Ncurses Tweaks; Revert RTL BW changes; #125 2023-05-21 13:39:49 -04:00
lwvmobile
4c91588af6 Re-enable P1 Heuristics On TCH and Non CS modes; 2023-05-21 09:14:02 -04:00
lwvmobile
35c05654a5 Fix NXDN/Scanner Bug; 2023-05-19 19:03:20 -04:00
lwvmobile
fbc9b5fab8 Reverting a few minor RTL tweaks; #125 2023-05-19 18:10:12 -04:00
lwvmobile
1126ab6578 P25 - Allow P2 6000sps on C4FM and QPSK; 2023-05-19 17:39:39 -04:00
lwvmobile
0842613b24 RTL - RMS based soft squelch and tweaks; #125 2023-05-19 11:27:13 -04:00
lwvmobile
bf4a4b574c RTL Misc; Disable Offset and Double BW; #125 2023-05-19 06:42:55 -04:00
lwvmobile
380657679e More LZ Tweaks; #123 2023-05-18 18:55:14 -04:00
lwvmobile
0a214af29b RTL ifdef tag additions; #125 2023-05-18 18:47:16 -04:00
lwvmobile
b008122149 More RTL Tweaks; #125 2023-05-18 10:22:05 -04:00
lwvmobile
7b6feb9e4f Attempt Fix/Clean on RTL input code; #125 2023-05-18 09:29:44 -04:00
lwvmobile
e4861bf94c Fix Idas Trunking Issue; #115 2023-05-17 16:23:22 -04:00
lwvmobile
587a3f01a2 Lima Zulu Tweaks III; #123 2023-05-17 07:37:28 -04:00
56 changed files with 2503 additions and 1067 deletions

View File

@@ -3,7 +3,7 @@
#Arch currently on 3.26.3
#Cygwin currently using 3.23.2 (or newer)
cmake_minimum_required(VERSION 3.10.2)
project(dsd-fme-zdev)
project(dsd-fme)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
#Set curses to ncurses, and wide true for ascii
@@ -31,11 +31,11 @@ if (PVC)
add_definitions(-DPVCONVENTIONAL)
endif ()
#use cmake option -DNXDN=ON to enable new NXDN Sync Pattern Testing
#use cmake option -DNXDN=ON to enable the old NXDN Sync Pattern
option(NXDN
"Build with new NXDN Sync Pattern Testing Enabled" OFF)
"Build with Old NXDN Sync Pattern Enabled" OFF)
if (NXDN)
add_definitions(-DNXDNTESTSYNC)
add_definitions(-DNXDNOLDSYNC)
endif ()
#use cmake option -DLZ=ON to enable LimaZulu Requested NXDN Tweaks
@@ -45,6 +45,20 @@ if (LZ)
add_definitions(-DLIMAZULUTWEAKS)
endif ()
#use cmake option -DTONES to change default location of the tones.wav files (lwvmobile precompiled 'Aero' releases only)
option(NXDN
"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(NXDN
"change designation of this build from MAIN to zDEV" OFF)
if (ZDEV)
add_definitions(-DZDEV_BUILD)
endif ()
include(git_revision)
git_describe(GIT_TAG)
@@ -77,24 +91,24 @@ list(APPEND SRCS "${CMAKE_CURRENT_BINARY_DIR}/git_ver.c")
include_directories("${PROJECT_SOURCE_DIR}/include")
ADD_EXECUTABLE(dsd-fme-zdev ${SRCS} ${HEADERS})
TARGET_LINK_LIBRARIES(dsd-fme-zdev ${LIBS})
ADD_EXECUTABLE(dsd-fme ${SRCS} ${HEADERS})
TARGET_LINK_LIBRARIES(dsd-fme ${LIBS})
include(GNUInstallDirs)
install(TARGETS dsd-fme-zdev DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS dsd-fme DESTINATION ${CMAKE_INSTALL_BINDIR})
# man page
find_program(HELP2MAN_FOUND help2man)
if (HELP2MAN_FOUND)
add_custom_command(TARGET dsd-fme-zdev POST_BUILD
add_custom_command(TARGET dsd-fme POST_BUILD
COMMAND help2man
ARGS -n "Digital Speech Decoder"
--version-string=${GIT_TAG}
-o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-zdev.1
-o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1
--no-info
$<TARGET_FILE:dsd-fme-zdev>
$<TARGET_FILE:dsd-fme>
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-zdev.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif()
# uninstall target

View File

@@ -1,8 +1,18 @@
## Notice
This branch is for development and experimentation. Results are not gauranteed to be stable.
This branch will also attempt to consolidate the code bases for 'Main' and 'Aero' into one codeset
with the differences needed for Aero (Cygwin) handled by cmake option `cmake -DAERO=ON ..` when building.
# 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
[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, 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-fme3.png)
## Information
See the [examples](https://github.com/lwvmobile/dsd-fme/tree/main/examples "examples") folder for information on [cloning and installing](https://github.com/lwvmobile/dsd-fme/blob/main/examples/Install_Notes.md "cloning and installing"), [example usage](https://github.com/lwvmobile/dsd-fme/blob/main/examples/Example_Usage.md "example usage"), and [trunking examples](https://github.com/lwvmobile/dsd-fme/blob/main/examples/trunking.sh "trunking examples").
## License
Copyright (C) 2010 DSD Author

View File

@@ -0,0 +1,23 @@
#! /bin/bash
clear
echo DSD-FME Digital Speech Decoder - Florida Man Edition Auto Installer
echo This will clone, build, and install DSD-FME only.
echo If you need dependencies installed, please run download-and-install.sh instead.
echo
read -p "Press enter to continue"
git clone https://github.com/lwvmobile/dsd-fme
cd dsd-fme
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig

67
download-and-install.sh Normal file
View File

@@ -0,0 +1,67 @@
#! /bin/bash
clear
echo DSD-FME Digital Speech Decoder - Florida Man Edition Auto Installer
echo MBELib is considered a requirement on this build.
echo You must view this notice prior to continuing.
echo The Patent Notice can be found at the site below.
echo https://github.com/lwvmobile/mbelib#readme
echo Please confirm that you have viewed the patent notice by entering y below.
echo
echo y/N
read ANSWER
Y='y'
if [[ $Y == $ANSWER ]]; then
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
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.
read -p "Press enter to continue"
#wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
#tar xjf itpp*
#if you can't cd into this folder, double check folder name first
#cd itpp-4.3.1
#mkdir build
#cd build
#cmake ..
#make -j `nproc`
#sudo make install
#sudo ldconfig
#cd ..
#cd ..
git clone https://github.com/lwvmobile/mbelib
cd mbelib
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
cd ..
cd ..
git clone https://github.com/lwvmobile/dsd-fme
cd dsd-fme
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
else
echo
echo Sorry, you cannot build DSD-FME without acknowledging the Patent Notice.
fi

BIN
dsd-fme-qgis-map.qgz Normal file

Binary file not shown.

BIN
dsd-fme2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
dsd-fme3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

193
examples/Example_Usage.md Normal file
View File

@@ -0,0 +1,193 @@
### 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.
```
-ft XDMA decoder class (P25 1 and 2, and DMR Stereo)
-fs DMR Stereo, also may need to use -xr if inverted DMR
-fa Legacy Auto (not recommended)
-fi NXDN48
-fn NXDN96
-fp ProVoice
-fm dPMR, also may need to use -xd if inverted dPMR.
-fr DMR Mono, also may need to use -xr if inverted DMR.
-f1 P25P1
-f2 P25P2 (may need to specify wacn/sys/nac manually)
-fx X2-TDMA
```
## 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 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.
To scan through a mixture of DMR and P25 Conventional, use:
`dsd-fme -i tcp -C channel_map.csv -G group.csv -Y -U 4532 -N 2> log.ans`
To scan through NXDN48 only conventional, use:
`dsd-fme -fi -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans`
To scan through NXDN96 only conventional, use:
`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.~~
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.
## Trunking Examples
Please see trunking.sh for sample start up scripts or scroll down to the bottom for more explanation.
## Example Usage - Default Decoder, Ncurses Terminal, Pulse Input/Output, and Log Console to file
`dsd-fme -N 2> voice.log`
and in a second terminal tab, same folder, run
`tail -n 40 -f voice.log`
Then you can open up your pavucontrol "Pulse Audio Volume Control" or "Volume Control" application and route input into DSD-FME from any application and DSD-FME output to the left and right speakers respectively. (unlock the channel in the application stream and adjust left and right independently)
### Input ###
--TCP Direct Audio Link with SDR++
`dsd-fme -i tcp` Currently defaults to localhost:7355 (SDR++ defaults)
`dsd-fme -i tcp:192.168.7.5:7356` (remote host and custom port)
--48000/9600 Mono Wav File Input
`dsd-fme -i filename.wav` 48k/1 Audio (SDR++, GQRX wav recordings)
`dsd-fme -i filename.wav -s 96000` 96k/1 (DSDPlus Raw Signal Wav Files)
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
Short Setup (all default values):
`dsd-fme -i rtl`
Detailed Setup:
`dsd-fme -ft -i rtl:0:154.9875M:26:-2:8:0:6020 `
```
RTL-SDR options:
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
freq <num> RTL-SDR Frequency (851800000 or 851.8M)
gain <num> RTL-SDR Device Gain (0-49)(default = 0; Hardware AGC recommended)
ppm <num> RTL-SDR PPM Error (default = 0)
bw <num> RTL-SDR Bandwidth kHz (default = 12)(8, 12, 16, 24)
sq <num> RTL-SDR Squelch Level vs RMS Value (Optional)
udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)
Example: dsd-fme-zdev -fs -i rtl -C cap_plus_channel.csv -T
Example: dsd-fme-zdev -fp -i rtl:0:851.375M:22:-2:24:0:6021
```
## Example Usage - Extra Payload/PDU Logging
`dsd-fme -Z -N 2> log.ans`
and in a second terminal tab, same folder, run
`tail -n 40 -f log.ans`
### EDACS/P25/NXDN/DMR Simple/Single VFO Trunking ###
EDACS Trunking (w/ channel map import)
--EDACS/PV Trunking using RIGCTL and TCP Direct Link Audio inside of SDR++ (Tested and Working on EDACS/EDACS-EA with Provoice only, no analog voice monitoring)
`dsd-fme -i tcp -fp -C channel_map.csv -G group.csv -T -U 4532 -N 2> log.ans`
--NXDN48 Trunking (standard band plan) with SDR++ (untested for frequency accuracy)
`dsd-fme -fi -i tcp -T -U 4532 -N 2> log.ans`
--NXDN48 Trunking (w/ channel map import) with SDR++ (put control channel frequency at channel 0 in channel_map.csv)
`dsd-fme -fi -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans`
--DMR Trunking (w/ channel map import) with SDR++ (put control channel frequency at channel 0 (TIII and Con+) in channel_map.csv)
`dsd-fme -fs -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans`
--P25 Trunking P1 and P2 (C4FM) with SDR++
`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)
`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)
`dsd-fme -i tcp -T -U 4532 -N -f2 -m2 2> log.ans`
Trunking Note1: All samples above can also be run with the RTL input method and setting of RTL UDP remote port. In terms of performance, however, SDR++ will do a much better job on weaker/marginal signal compared to the RTL input. RTL input should only be used on strong signal.
`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 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.
```
Talkgroup Voice Channel Grant (TV_GRANT) - Logical
Ch [036] Cd [0054] C+ [0110] - TS [1] - Target [01900500] - Source [01900505]
```
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.
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.
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 Type-D/IDAS Update: Type-D or IDAS decoding/trunking has been coded now and tested on a small two channel system. Set up a channel map much like Type-C trunking. If preferred, insert channel 31 at the top of your channel map for the 'home repeater' or go to channel of choice during a TX_REL or DISC message. Extensive testing of Type-D has not been conducted. Some cavaets may currently include iffy per call wav file saving and potentially shifting SRC and TGT ID values due to how SCCH messages are handled and how Busy Repeater Messages are handled. Private calls will need to be enabled by enabling 'data calls', if desired. During testing, only data calls came on private calls, so this was set to disabled by default, but can be enabled with data calls enabled. Also, note that some home repeater channels may or may not carry calls from all systems.
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.
## NCurses Keyboard Shortcuts ##
Some Keyboard Shortcuts have been implemented for testing to see how users like them. Just hope nobody pushes a key on accident and doesn't know which one it was or what it does. The current list of keyboard shortcuts include:
```
esc or arrow keys - ncurses menu
q - quit
c - toggle compact mode
h - toggle call history
z - toggle console payloads
a - toggle call alert beep
4 - force privacy/scrambler key assertion over enc identifiers (dmr and nxdn)
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)
m - toggle c4fm/qpsk 10/4 (everything but phase 2 signal)
M - toggle c4fm/qpsk 8/3 (phase 2 tdma control channel)
R - start capturing symbol capture bin (date/time name file)
r - stop capturing symbol capture bin
spacebar - replay last symbol capture bin (captures must be stopped first)
s - stop playing symbol capture bin or wav input file
P - start per call decoded wav files (Capital P)
p - stop per call decoded wav files (Lower p)
t - toggle trunking (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
2 - Lockout Tuning/Playback of TG in Slot 2 -- Current Session Only if no group.csv file specified
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
g - Toggle Trunking Tuning to Group Calls (DMR T3, Con+, Cap+, P25, NXDN)
u - Toggle Trunking Tuning to Private Calls (DMR T3, Cap+, P25)
d - Toggle Trunking Tuning to Data Calls (DMR T3, NXDN)
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)
```

164
examples/Install_Notes.md Normal file
View File

@@ -0,0 +1,164 @@
## How to clone and build this branch
### 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.
If you need all dependencies build and installed first (only on Debian/Ubuntu/Mint/Pi), run:
```
wget https://raw.githubusercontent.com/lwvmobile/dsd-fme/main/download-and-install.sh
chmod +x 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:
```
wget https://raw.githubusercontent.com/lwvmobile/dsd-fme/main/download-and-install-nodeps.sh
chmod +x download-and-install-nodeps.sh
./download-and-install-nodeps.sh
```
## 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.
Debian/Mint/Ubuntu/Pi
```
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
```
Fedora 36/37 -- 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++
```
## 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.
```
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!!
```
wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
tar xjf itpp*
#if you can't cd into this folder, double check folder name first
cd itpp-4.3.1
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
cd ..
cd ..
```
MBELib is considered a requirement in this build. You must read this notice prior to continuing. [MBElib Patent Notice](https://github.com/lwvmobile/mbelib#readme "MBElib Patent Notice") This version of MBELib is 1.3.2 and prints to STDERR, using the stock 1.3.0 MBElib may cause problems with print alignments if paired with this version of DSD-FME, or cause future compatibility issues.
```
git clone https://github.com/lwvmobile/mbelib
cd mbelib
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
cd ..
cd ..
```
Note: Some environment/distro users (Cygwin, Arch, and others) may need to manually copy any libmbe files found in the build folder to the /usr/lib folder on root.
`sudo cp libmbe* /usr/lib`
Finish by running these steps to clone and build DSD-FME.
```
git clone https://github.com/lwvmobile/dsd-fme
cd dsd-fme
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
```
### Windows Cygwin Builds
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_sink2 sink_properties=device.description=Virtual_Sink2
```
Already have this branch, and just want to pull the latest build? You can run the rebuild.sh file in the dsd-fme folder, or manually do the pull with the commands:
```
##Open your clone folder##
git pull
##cd into your build folder##
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
```
If the call alert wav files aren't playing, then make sure to run the following in the dsd-fme folder to copy the wav files to the /usr/share/ folder and give them adequate permission to be accessed.
```
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
```

View File

@@ -0,0 +1,10 @@
LSN(dec),frequency(Hz) (do not delete this line or won't import properly)
1,858606250
2,858606250
3,859606250
4,859606250
5,860606250
6,860606250
7,861606250
8,861606250
1 LSN(dec) frequency(Hz) (do not delete this line or won't import properly)
2 1 858606250
3 2 858606250
4 3 859606250
5 4 859606250
6 5 860606250
7 6 860606250
8 7 861606250
9 8 861606250

View File

@@ -0,0 +1,19 @@
ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
999,862093750,default cc (come here first), optional use non-existent channel as first entry
1,863093750
2,862093750
3,861093750
4,860093750
5,859093750
6,863593750
7,862593750
8,861593750
9,860593750
10,859593750
11,863393750
12,862393750
13,861393750
14,860393750
15,859393750
1 ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
2 999,862093750,default cc (come here first), optional use non-existent channel as first entry
3 1,863093750
4 2,862093750
5 3,861093750
6 4,860093750
7 5,859093750
8 6,863593750
9 7,862593750
10 8,861593750
11 9,860593750
12 10,859593750
13 11,863393750
14 12,862393750
15 13,861393750
16 14,860393750
17 15,859393750

8
examples/dmr_t3_chan.csv Normal file
View File

@@ -0,0 +1,8 @@
ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
999,456318750,default cc (come here first), optional use non-existent channel as first entry
36,455756250
54,455981250
81,456318750
1 ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
2 999,456318750,default cc (come here first), optional use non-existent channel as first entry
3 36,455756250
4 54,455981250
5 81,456318750

View File

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

5
examples/group.csv Normal file
View File

@@ -0,0 +1,5 @@
DEC,Mode(A- Allow, B - Block, DE - Digital Enc),Name of Group,Tag (do not delete this line or won't import properly)
100,B,Example Name,Tag
1449,A,Fire Dispatch,Fire
929,A,Fire Tac,Fire
22033,DE,Law Dispatch,Law
1 DEC,Mode(A- Allow, B - Block, DE - Digital Enc),Name of Group,Tag (do not delete this line or won't import properly)
2 100,B,Example Name,Tag
3 1449,A,Fire Dispatch,Fire
4 929,A,Fire Tac,Fire
5 22033,DE,Law Dispatch,Law

View File

@@ -0,0 +1,10 @@
LSN(dec),frequency(Hz) (do not delete this line or won't import properly)
1,858606250
2,858606250
3,859606250
4,859606250
5,860606250
6,860606250
7,861606250
8,861606250
1 LSN(dec) frequency(Hz) (do not delete this line or won't import properly)
2 1 858606250
3 2 858606250
4 3 859606250
5 4 859606250
6 5 860606250
7 6 860606250
8 7 861606250
9 8 861606250

6
examples/multi_key.csv Normal file
View File

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

View File

@@ -0,0 +1,5 @@
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

@@ -0,0 +1,8 @@
channel(dec), freq(Hz)
141,423862500
142,424337500
143,424912500
203,424100000
204,424625000
271,422650000
302,423287500
1 channel(dec) freq(Hz)
2 141 423862500
3 142 424337500
4 143 424912500
5 203 424100000
6 204 424625000
7 271 422650000
8 302 423287500

5
examples/nxdn_sc_key.csv Normal file
View File

@@ -0,0 +1,5 @@
key(dec) or tg(dec), value(dec), load any single keys as key 0
0,23466
1,12345
2,32700
63,32767
1 key(dec) or tg(dec), value(dec), load any single keys as key 0
2 0,23466
3 1,12345
4 2,32700
5 63,32767

45
examples/trunking.sh Normal file
View File

@@ -0,0 +1,45 @@
#example trunking sh scripts (SDR++ with RIGCTL and RTL Input)
#make sure to put a # in front of all lines except the one you wish to use
#P25 P1 FDMA CC with C4FM
#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
#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 rtl:0:855.625M:0:-2:12 -T -mq -N 2> log.ans
#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 rtl:0:855.625M:0:-2:12 -T -f2 -m2 -N 2> log.ans
#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 rtl:0:450M:44:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans
#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 rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
#NXDN48 Type-C or Type-D Trunking with Channel Map
#dsd-fme -fi -i tcp -T -U 4532 -C nxdn_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
#NXDN48 Type-C Trunking with DFA
#dsd-fme -fi -i tcp -T -U 4532 -N 2> log.ans
#dsd-fme -fi -i rtl:0:855.625M:0:-2:12:100 -T -N 2> log.ans
#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
#and 7355 as the default port number. -U is the port number for RIGCTL and will mirror the tcp hostname
#running under the assumption that the user will be connnecting the VFO to the same instance of SDR++
#You can also specify an ip address to connect to a remote SDR++ instance, make sure that the settings
#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
#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

View File

@@ -270,6 +270,7 @@ typedef struct
int rtl_udp_port;
int rtl_bandwidth;
int rtl_started;
int rtl_rms;
int monitor_input_audio;
int pulse_raw_rate_in;
int pulse_raw_rate_out;
@@ -373,12 +374,15 @@ typedef struct
uint8_t trunk_tune_enc_calls;
//OSS audio - slot preference
uint8_t slot_preference;
int slot_preference;
//'DSP' Format Output
uint8_t use_dsp_output;
char dsp_out_file[2048];
//Use P25p1 heuristics
uint8_t use_heuristics;
} dsd_opts;
typedef struct
@@ -1008,8 +1012,10 @@ uint8_t crc8(uint8_t bits[], unsigned int len);
bool crc8_ok(uint8_t bits[], unsigned int len);
uint8_t crc7(uint8_t bits[], unsigned int len);
//LFSR code courtesy of https://github.com/mattames/LFSR/
//LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/
void LFSR(dsd_state * state);
void LFSRP(dsd_state * state);
void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state);
void LFSR64(dsd_state * state);
@@ -1051,6 +1057,7 @@ bool QR_16_7_6_decode(unsigned char *rxBits);
void InitAllFecFunction(void);
void resetState (dsd_state * state);
void reset_dibit_buffer(dsd_state * state);
void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]);
//P25 PDU Handler
@@ -1096,7 +1103,8 @@ unsigned long long int edacs_bch (unsigned long long int message);
int csvGroupImport(dsd_opts * opts, dsd_state * state);
int csvLCNImport(dsd_opts * opts, dsd_state * state);
int csvChanImport(dsd_opts * opts, dsd_state * state);
int csvKeyImport(dsd_opts * opts, dsd_state * state);
int csvKeyImportDec(dsd_opts * opts, dsd_state * state);
int csvKeyImportHex(dsd_opts * opts, dsd_state * state);
#ifdef __cplusplus
extern "C" {
@@ -1107,6 +1115,9 @@ void open_rtlsdr_stream(dsd_opts *opts);
void cleanup_rtlsdr_stream();
void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state);
void rtlsdr_sighandler();
void rtl_dev_tune(dsd_opts * opts, long int frequency);
int rtl_return_rms();
void rtl_clean_queue();
#endif
//DMR TRELLIS
void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload);

12
install.sh Normal file
View File

@@ -0,0 +1,12 @@
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig

16
rebuild.sh Normal file
View File

@@ -0,0 +1,16 @@
#! /bin/bash
clear
echo DSD-FME Digital Speech Decoder - Florida Man Edition
echo Automatic Git Pull and Rebuild
echo
sleep 1
##Open your clone folder##
git pull
sleep 2
##cd into your build folder##
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig

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->data_header_valid, 0, sizeof(state->data_header_valid));
memset (state->data_header_format, 7, sizeof(state->data_header_format));
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
//reset some strings -- resetting call string here causes random blink on ncurses terminal (cap+)
// sprintf (state->call_string[0], "%s", " "); //21 spaces
// sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->dmr_lrrp_gps[0], "%s", "");
sprintf (state->dmr_lrrp_gps[1], "%s", "");
}

View File

@@ -339,8 +339,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//process embedded link control
fprintf (stderr, "\n");
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
//check the single burst/reverse channel opportunity
dmr_sbrc (opts, state, power);
//check the single burst/reverse channel opportunity -- moved
// dmr_sbrc (opts, state, power);
}
if (internalslot == 1 && vc2 == 6)
@@ -348,8 +349,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//process embedded link control
fprintf (stderr, "\n");
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
//check the single burst/reverse channel opportunity
dmr_sbrc (opts, state, power);
//check the single burst/reverse channel opportunity -- moved
// dmr_sbrc (opts, state, power);
}
if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here
@@ -381,6 +383,10 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
cach_err = dmr_cach (opts, state, cachdata);
if (opts->payload == 0) fprintf (stderr, "\n");
//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);
// run alg refresh after vc6 ambe processing
if (internalslot == 0 && vc1 == 6) dmr_alg_refresh (opts, state);
if (internalslot == 1 && vc2 == 6) dmr_alg_refresh (opts, state);

View File

@@ -249,13 +249,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
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
#endif
}
}
@@ -1055,14 +1057,16 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
j = 11; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
#ifdef USE_RTLSDR
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];
opts->p25_is_tuned = 1;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
j = 11; //break loop
#endif
}
}
@@ -1198,15 +1202,17 @@ 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
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_chan_map[lcn]);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, 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;
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.
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
#endif
}
}
@@ -1393,17 +1399,19 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
j = 11; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//debug
fprintf (stderr, " - Freq: %ld", state->trunk_chan_map[j+xpt_bank+1]);
rtl_udp_tune (opts, state, state->trunk_chan_map[j+xpt_bank+1]);
rtl_dev_tune (opts, 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;
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away
j = 11; //break loop
#endif
}
}

View File

@@ -336,8 +336,9 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
else if (opts->audio_in_type == 3) //rtl_fm tuning
{
//UDP command to tune the RTL dongle
rtl_udp_tune(opts, state, state->p25_cc_freq);
#ifdef USE_RTLSDR
rtl_dev_tune(opts, state->p25_cc_freq);
#endif
}
opts->p25_is_tuned = 0;
//zero out vc frequencies

View File

@@ -342,6 +342,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
state->payload_miR = 0;
state->payload_keyidR = 0;
}
}
@@ -520,17 +521,35 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
if (state->K1 != 0 && fid == 0x68 && so & 0x40)
{
fprintf (stderr, "\n");
if (state->K2 != 0) fprintf (stderr, "\n ");
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->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:
//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)
{
fprintf(stderr, " FLCO=0x%02X FID=0x%02X ", flco, fid);

View File

@@ -13,6 +13,23 @@ void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc,
{
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
state->late_entry_mi_fragment[slot][vc][0] = (uint64_t)ConvertBitIntoBytes(&ambe_fr[3][0], 4);
@@ -183,7 +200,6 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
//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
//unknown what the other values are (see Cap+ 0x313 and 0x643)
if (power == 1) //RC
{
crc_extracted = 0;
@@ -198,17 +214,19 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
}
else crc_okay = 1; //SB
if (opts->payload == 1) //hide the sb/rc behind the payload printer, won't be useful to most people right now
for(i = 0; i < 11; i++)
{
sbrc_hex = sbrc_hex << 1;
sbrc_hex |= sbrc_return[i] & 1; //sbrc_return
}
if (opts->payload == 1) //hide the sb/rc behind the payload printer, won't be useful to most people
{
fprintf (stderr, "\n %s", KCYN);
if (power == 0) fprintf (stderr, " SB: ");
if (power == 1) fprintf (stderr, " RC: ");
for(i = 0; i < 11; i++)
{
sbrc_hex = sbrc_hex << 1;
sbrc_hex |= sbrc_return[i] & 1; //sbrc_return
fprintf (stderr, "%d", sbrc_return[i]);
}
fprintf (stderr, " - %03X", sbrc_hex);
fprintf (stderr, "%s", KNRM);
@@ -217,82 +235,73 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
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);
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;
uint8_t sbrc_opcode = sbrc_hex;
uint8_t alg = sbrc_hex & 0x7;
uint8_t key = (sbrc_hex >> 3) & 0xFF;
uint8_t cap_site = (sbrc_hex >> 4) & 0x7; //signalling on Cap+ when voice errors (non voice VC6 is present)
//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 (1 == 1) //opts->payload == 1
{
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
//else if (placeholder for future conditions)
// {
// placeholder for future conditions
// }
else //Finally have a consistent set-up for this
{
//the signalling here is always presents on good voice frames, if errs are [3][2] then its not a VC6 voice frame, but some other 'hidden' frame
if (slot == 0 && 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, "%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);
// 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
// {
state->payload_keyid = key;
state->payload_algid = alg + 0x20; //assuming DMRA approved alg values (moto patent)
}
// 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)
// }
// }
//the signalling here is always presents on good voice frames, if errs are [3][2] then its not a VC6 voice frame, but some other 'hidden' frame
if (slot == 1 && 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, "%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_keyidR = key;
state->payload_algidR = alg + 0x20; //assuming DMRA approved alg values (moto patent)
}
// }
// }
}
}
}
}
}
SBRC_END:

View File

@@ -600,7 +600,15 @@ openAudioInDevice (dsd_opts * opts)
}
else if(strncmp(opts->audio_in_dev, "rtl", 3) == 0)
{
#ifdef USE_RTLSDR
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)
{

View File

@@ -283,12 +283,12 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0;
//disabling again, causing issues with trunking P25
if (state->synctype == 1 && opts->p25_trunk == 1)
{
// Use the P25 heuristics if available
// valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit);
}
//testing again, either on Voice channels only (when tuned) or with trunk disabled
if (state->synctype == 1 && (opts->p25_is_tuned == 1 || opts->p25_trunk == 0) && opts->use_heuristics == 1)
{
// Use the P25p1 heuristics if available
valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit);
}
if (valid == 0)
{
@@ -347,12 +347,12 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0;
//disabling again, causing issues with trunking P25
if (state->synctype == 0 && opts->p25_trunk == 1)
{
// Use the P25 heuristics if available
// valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit);
}
//testing again, either on Voice channels only (when tuned) or with trunk disabled
if (state->synctype == 0 && (opts->p25_is_tuned == 1 || opts->p25_trunk == 0) && opts->use_heuristics == 1)
{
// Use the P25p1 heuristics if available
valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit);
}
if (valid == 0)
{

View File

@@ -189,10 +189,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[state->lcn_freq_roll]);
}
//rtludp
//rtl
if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_lcn_freq[state->lcn_freq_roll]);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, state->trunk_lcn_freq[state->lcn_freq_roll]);
#endif
}
fprintf (stderr, "Tuning to Frequency: %.06lf MHz\n",
@@ -446,6 +448,21 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
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) //tests show floor level around 40, and signal breaking 100, default is 100 for level
{
if (opts->frame_nxdn48 == 1 || opts->frame_nxdn96 == 1 || opts->frame_dpmr == 1)
{
//should we update min/max here? yes or no?
// state->max = ((state->max) + lmax) / 2;
// state->min = ((state->min) + lmin) / 2;
goto SYNC_TEST_END;
}
}
strncpy (synctest, (synctest_p - 23), 24);
if (opts->frame_p25p1 == 1)
{
@@ -1277,120 +1294,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
#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
#ifdef NXDNOLDSYNC //Use FSW vs strncmperr method
//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))
@@ -1401,7 +1305,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//Preamble plus FSW, proceed right away
if ( (strncmperr (synctest19, NXDN_PANDFSW, 19, 1) == 0) )
{
// state->carrier = 1;
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
@@ -1414,7 +1318,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest19, INV_NXDN_PANDFSW, 19, 1) == 0) )
{
// state->carrier = 1;
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
@@ -1427,7 +1331,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest10, NXDN_FSW, 10, 1) == 0) )
{
// state->carrier = 1;
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
@@ -1445,7 +1349,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
else if ( (strncmperr (synctest10, INV_NXDN_FSW, 10, 1) == 0) )
{
// state->carrier = 1;
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
@@ -1462,6 +1366,125 @@ 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
//Provoice Conventional -- Some False Positives due to shortened frame sync pattern, so use squelch if possible
@@ -1551,6 +1574,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
#endif //End Provoice Conventional
SYNC_TEST_END: ; //do nothing
} // t >= 10
if (exitflag == 1)

View File

@@ -146,7 +146,8 @@ int csvChanImport(dsd_opts * opts, dsd_state * state) //channel map import
return 0;
}
int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support
//Decimal Variant of Key Import
int csvKeyImportDec(dsd_opts * opts, dsd_state * state) //multi-key support
{
char filename[1024] = "filename.csv";
sprintf (filename, "%s", opts->key_in_file);
@@ -210,3 +211,48 @@ int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support
fclose(fp);
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;
}

View File

@@ -51,8 +51,8 @@ char * FM_banner[9] = {
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
" ██║ ██║╚█████╗ ██║ ██║ Lima ███║ ███╔═╝",
" ██║ ██║ ╚═══██╗██║ ██║ Zulu ███║ ██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝ Edition III ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ Windows 32-bit╚═══════╝╚══════╝",
" ██████╔╝██████╔╝██████╔╝ Edition V ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═══════╝╚══════╝",
" "
};
#else
@@ -90,10 +90,29 @@ void
noCarrier (dsd_opts * opts, dsd_state * state)
{
//clear heuristics from last carrier signal
if (opts->frame_p25p1 == 1 && opts->use_heuristics == 1)
{
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
}
//only do it here on the tweaks
#ifdef LIMAZULUTWEAKS
state->nxdn_last_ran = -1;
state->nxdn_last_rid = 0;
state->nxdn_last_tg = 0;
#endif
//experimental conventional frequency scanner mode
if (opts->scanner_mode == 1 && ( (time(NULL) - state->last_cc_sync_time) > opts->trunk_hangtime))
{
//always do these -- makes sense during scanning
state->nxdn_last_ran = -1;
state->nxdn_last_rid = 0;
state->nxdn_last_tg = 0;
if (state->lcn_freq_roll >= state->lcn_freq_count)
{
state->lcn_freq_roll = 0; //reset to zero
@@ -107,13 +126,16 @@ noCarrier (dsd_opts * opts, dsd_state * state)
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[state->lcn_freq_roll]);
}
//rtludp
//rtl
if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_lcn_freq[state->lcn_freq_roll]);
#ifdef USE_RTLSDR
rtl_dev_tune(opts, state->trunk_lcn_freq[state->lcn_freq_roll]);
#endif
}
if (state->lastsynctype != -1) fprintf (stderr, "Resume Scanning Mode\n");
//print here not working as it should -- not always a -1 value on lastsynctype I presume
// if (state->lastsynctype != -1) fprintf (stderr, "Resume Scanning Mode\n");
}
state->lcn_freq_roll++;
@@ -142,25 +164,29 @@ noCarrier (dsd_opts * opts, dsd_state * state)
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
state->dmr_rest_channel = -1; //maybe?
}
else if (opts->audio_in_type == 3) //rtl_fm tuning
//rtl
else if (opts->audio_in_type == 3)
{
//UDP command to tune the RTL dongle
rtl_udp_tune(opts, state, state->p25_cc_freq);
state->dmr_rest_channel = -1; //maybe?
#ifdef USE_RTLSDR
rtl_dev_tune (opts, state->p25_cc_freq);
state->dmr_rest_channel = -1;
#endif
}
opts->p25_is_tuned = 0;
state->edacs_tuned_lcn = -1;
//only for EDACS/PV
if (opts->frame_provoice == 1 && opts->wav_out_file != NULL)
if (opts->p25_trunk == 1 && opts->frame_provoice == 1 && opts->wav_out_file != NULL)
{
closeWavOutFile(opts, state);
}
state->last_cc_sync_time = time(NULL);
//test to switch back to 10/4 P1 QPSK for P25 FDMA CC
if (opts->mod_qpsk == 1 && state->p25_cc_is_tdma == 0)
//reworked to always change back to 10/4 if p25_cc_is_tdma is set to 0 or 1 (inits on 2)
if (state->p25_cc_is_tdma == 0) //is set on signal from P25 TSBK or MAC_SIGNAL
{
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
@@ -348,7 +374,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
//unload keys when using keylaoder
if (state->keyloader == 1)
{
state->R = 0; //NXDN
state->R = 0; //NXDN, or RC4 (slot 1)
state->RR = 0; //RC4 (slot 2)
state->K = 0; //BP
state->K1 = 0; //tera 10 char BP
state->H = 0; //shim for above
@@ -507,14 +534,18 @@ initOpts (dsd_opts * opts)
opts->delay = 0;
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0;
//all RTL user options -- enabled AGC by default due to weak signal related issues
opts->rtl_dev_index = 0; //choose which device we want by index number
opts->rtl_gain_value = 26; //mid value, 0 - AGC (not recommended) 49 highest value
opts->rtl_squelch_level = 0; //fully open by default, want to specify level for things like NXDN with false positives
opts->rtl_volume_multiplier = 1; //sample multiplier; 1 seems like a good value
opts->rtl_udp_port = 6020; //set UDP port for RTL remote
opts->rtl_bandwidth = 12; //changed recommended default to 12, 24 for ProVoice
opts->rtlsdr_ppm_error = 0; //initialize ppm with 0 value; bug reported by N.
opts->rtl_gain_value = 0; //mid value, 0 - AGC - 0 to 49 acceptable values
opts->rtl_squelch_level = 100; //100 by default, but only affects NXDN and dPMR during framesync test, compared to RMS value
opts->rtl_volume_multiplier = 1; //sample multiplier; This multiplies the sample value to produce a higher 'inlvl' (probably best left unused)
opts->rtl_udp_port = 0; //set UDP port for RTL remote -- 0 by default, will be making this optional for some external/legacy use cases (edacs-fm, etc)
opts->rtl_bandwidth = 12; //default is 12, reverted back to normal on this (no inherent benefit)
opts->rtlsdr_ppm_error = 0; //initialize ppm with 0 value;
opts->rtlsdr_center_freq = 850000000; //set to an initial value (if user is using a channel map, then they won't need to specify anything other than -i rtl if desired)
opts->rtl_started = 0;
opts->rtl_rms = 0; //root means square power level on rtl input signal
//end RTL user options
opts->pulse_raw_rate_in = 48000;
opts->pulse_raw_rate_out = 48000; //
opts->pulse_digi_rate_in = 48000;
@@ -533,14 +564,24 @@ initOpts (dsd_opts * opts)
opts->use_ncurses_terminal = 0;
opts->ncurses_compact = 0;
opts->ncurses_history = 1;
#ifdef LIMAZULUTWEAKS
opts->ncurses_compact = 1;
#endif
opts->payload = 0;
opts->inverted_dpmr = 0;
opts->dmr_mono = 0;
opts->dmr_stereo = 1;
opts->aggressive_framesync = 1;
//this may not matter so much, since its already checked later on
//but better safe than sorry I guess
#ifdef AERO_BUILD
opts->audio_in_type = 5;
opts->audio_out_type = 5;
#else
opts->audio_in_type = 0;
opts->audio_out_type = 0;
#endif
opts->lrrp_file_output = 0;
@@ -613,6 +654,9 @@ initOpts (dsd_opts * opts)
opts->dsp_out_file[0] = 0;
opts->use_dsp_output = 0;
//Use P25p1 heuristics
opts->use_heuristics = 0;
} //initopts
void
@@ -953,6 +997,7 @@ initState (dsd_state * state)
memset (state->late_entry_mi_fragment, 0, sizeof (state->late_entry_mi_fragment));
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
state->dPMRVoiceFS2Frame.CalledIDOk = 0;
state->dPMRVoiceFS2Frame.CallingIDOk = 0;
@@ -970,13 +1015,13 @@ usage ()
{
printf ("\n");
printf ("Usage: dsd-fme-aero [options] Decoder/Trunking Mode\n");
printf (" or: dsd-fme-aero [options] -r <files> Read/Play saved mbe data from file(s)\n");
printf (" or: dsd-fme-aero -h Show help\n");
printf ("Usage: dsd-fme [options] Decoder/Trunking Mode\n");
printf (" or: dsd-fme [options] -r <files> Read/Play saved mbe data from file(s)\n");
printf (" or: dsd-fme -h Show help\n");
printf ("\n");
printf ("Display Options:\n");
printf (" -N Use NCurses Terminal\n");
printf (" dsd-fme-aero -N 2> log.ans \n");
printf (" dsd-fme -N 2> log.ans \n");
printf (" -Z Log MBE/PDU Payloads to console\n");
printf ("\n");
printf ("Input/Output options:\n");
@@ -985,9 +1030,9 @@ usage ()
printf (" pulse for pulse audio (will require pactl running in Cygwin)\n");
#else
printf (" -i <device> Audio input device (default is pulse)\n");
//NOTE: Fix some inputs to /dev/audio if required for linux, or just leave it as the more annoying /dev/dsp -- padsp bug opens multiple input streams...sometimes
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" rtl for rtl dongle (Default Values -- see below)\n");
printf (" rtl:dev:freq:gain:ppm:bw:sq:udp for rtl dongle (see below)\n");
printf (" tcp for tcp client SDR++/GNURadio Companion/Other (Port 7355)\n");
printf (" tcp:192.168.7.5:7355 for custom address and port \n");
@@ -1009,7 +1054,6 @@ usage ()
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" null for no audio output\n");
// printf (" pulse for pulse audio \n");
printf (" -d <dir> Create mbe data files, use this directory (TDMA version is experimental)\n");
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
@@ -1020,32 +1064,33 @@ usage ()
printf (" -a Enable Call Alert Beep (NCurses Terminal Only)\n");
printf (" (Warning! Might be annoying.)\n");
printf (" -L <file> Specify Filename for LRRP Data Output.\n");
printf (" -Q <file> Specify Filename for DSP Structured File Output. (placed in DSP folder)\n");
printf (" -Q <file> Specify Filename for OK-DMRlib Structured File Output. (placed in DSP folder)\n");
printf (" -c <file> Output symbol capture to .bin file\n");
printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n");
printf (" -V Enable Audio Smoothing on Upsampled 48k/1 or 24k/2 Audio (Capital V)\n");
printf (" (Audio Smoothing is now disabled on all upsampled output by default -- fix crackle/buzz bug)\n");
printf (" -z Set TDMA Voice Slot Preference when using OSS audio output (prevent lag and stuttering)\n");
printf (" -z Set TDMA Voice Slot Preference when using /dev/dsp audio output (prevent lag and stuttering)\n");
printf ("\n");
printf ("RTL-SDR options:\n");
printf (" WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>\n");
printf (" Usage: rtl:dev:freq:gain:ppm:bw:sq:udp\n");
printf (" NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended\n");
printf (" dev <num> RTL-SDR Device Index Number\n");
printf (" freq <num> RTL-SDR Frequency (851800000 or 851.8M) \n");
printf (" gain <num> RTL-SDR Device Gain (0-49)(default = 26)(0 = Hardware AGC, not recommended)\n");
printf (" gain <num> RTL-SDR Device Gain (0-49)(default = 0; Hardware AGC recommended)\n");
printf (" ppm <num> RTL-SDR PPM Error (default = 0)\n");
printf (" bw <num> RTL-SDR VFO Bandwidth kHz (default = 12)(6, 8, 12, 24) \n");
printf (" sq <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)\n");
printf (" udp <num> RTL-SDR UDP Remote Port (default = 6020)\n");
printf (" Example: dsd-fme-aero -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
printf (" bw <num> RTL-SDR Bandwidth kHz (default = 12)(4, 6, 8, 12, 16, 24) \n");
printf (" sq <num> RTL-SDR Squelch Level vs RMS Value (Optional)\n");
printf (" udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)\n");
printf (" Example: dsd-fme -fs -i rtl -C cap_plus_channel.csv -T\n");
printf (" Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:24:0:6021\n");
printf ("\n");
printf ("Decoder options:\n");
printf (" -fa Legacy Auto Detection (old methods default)\n");
printf (" -ft XDMA P25 and DMR BS/MS frame types (new default)\n");
printf (" -fs DMR Stereo BS and MS Simplex\n");
printf (" -f1 Decode only P25 Phase 1\n");
printf (" -f2 Decode only P25 Phase 2 (6000 sps) **\n");
printf (" -fd Decode only D-STAR\n");
printf (" -fr Decode only DMR Mono - Single Slot Voice\n");
printf (" -fx Decode only X2-TDMA\n");
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
@@ -1058,6 +1103,7 @@ usage ()
printf (" -xd Expect inverted ICOM dPMR signal\n");
printf ("\n");
printf (" * denotes frame types that cannot be auto-detected.\n");
printf (" ** Phase 2 Single Frequency may require user to manually set WACN/SYSID/CC parameters if MAC_SIGNAL not present.\n");
printf ("\n");
printf ("Advanced Decoder options:\n");
printf (" -X <hex> Manually Set P2 Parameters (WACN, SYSID, CC/NAC)\n");
@@ -1075,18 +1121,19 @@ usage ()
printf (" -mc Use only C4FM modulation optimizations\n");
printf (" -mg Use only GFSK modulation optimizations\n");
printf (" -mq Use only QPSK modulation optimizations\n");
printf (" -m2 Use P25p2 6000 sps CQPSK modulation optimizations\n");
printf (" -m2 Use P25p2 6000 sps QPSK modulation optimizations\n");
//printf (" (4 Level, not 8 Level LSM) (this is honestly unknown since I can't verify what local systems are using)\n");
printf (" -F Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
printf (" Use this feature to allow MAC_SIGNAL even if CRC errors.\n");
printf (" -F Relax DMR RAS/CRC CSBK/DATA Pass/Fail\n");
printf (" Enabling on some systems could lead to bad voice/data decoding if bad or marginal signal\n");
printf (" Enabling on some systems could lead to bad channel assignments/site data decoding if bad or marginal signal\n");
printf (" -F Relax NXDN SACCH/FACCH/CAC/F2U CRC Pass/Fail\n");
printf (" Not recommended on NXDN, but can be bypassed if desired.\n");
printf ("\n");
printf (" -K <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
printf (" -b <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
printf (" (NOTE: This used to be the 'K' option! \n");
printf ("\n");
printf (" -H <hex> Manually Enter **tera 10/32/64 Char Privacy Hex Key (see example below)\n");
printf (" -H <hex> Manually Enter **tera 10/32/64 Char Basic Privacy Hex Key (see example below)\n");
printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n");
printf (" -H 0B57935150 \n");
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
@@ -1094,11 +1141,18 @@ usage ()
printf ("\n");
printf (" -R <dec> Manually Enter dPMR or NXDN EHR Scrambler Key Value (Decimal Value)\n");
printf (" \n");
printf (" -k <file> Import Key List from csv file.\n");
printf (" Only supports NXDN, DMR Basic Privacy and **tera 10-Char (decimal value) only. \n");
printf (" -1 <hex> Manually Enter RC4 Key Value (DMR, P25) (Hex Value) \n");
printf (" \n");
printf (" -k <file> Import Key List from csv file (Decimal Format) -- Lower Case 'k'.\n");
printf (" Only supports NXDN, DMR Basic Privacy (decimal value). \n");
printf (" (dPMR and **tera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n");
printf (" \n");
printf (" -4 Force Privacy Key over FID and SVC bits \n");
printf (" -K <file> Import Key List from csv file (Hexidecimal Format) -- Capital 'K'.\n");
printf (" Use for Hex Value **tera 10-char BP keys and RC4 10-Char Hex Keys. \n");
printf (" \n");
printf (" -4 Force Privacy Key over Encryption Identifiers (DMR BP and NXDN Scrambler) \n");
printf (" \n");
printf (" -0 Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR) \n");
printf ("\n");
printf (" Trunking Options:\n");
printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n");
@@ -1110,19 +1164,19 @@ usage ()
printf (" Experimental -- Can only scan for sync with enabled decoders, don't mix NXDN and DMR/P25!\n");
printf (" This is not a Trunking Feature, just scans through conventional frequencies fast!\n");
printf (" -W Use Imported Group List as a Trunking Allow/White List -- Only Tune with Mode A\n");
printf (" -p Disable Tune to Private Calls (DMR TIII and P25)\n");
printf (" -E Disable Tune to Group Calls (DMR TIII, Con+, Cap+ and P25)\n");
printf (" (NOTE: NXDN and EDACS, simply disable trunking if desired) \n");
printf (" -e Enable Tune to Data Calls (DMR TIII)\n");
printf (" -p Disable Tune to Private Calls (DMR TIII, P25, NXDN Type-C and Type-D)\n");
printf (" -E Disable Tune to Group Calls (DMR TIII, Con+, Cap+, P25, NXDN Type-C, and Type-D)\n");
printf (" -e Enable Tune to Data Calls (DMR TIII, Cap+, NXDN Type-C)\n");
printf (" (NOTE: No Clear Distinction between Cap+ Private Voice Calls and Data Calls -- Both enabled with Data Calls \n");
printf (" (NOTE: P25 Data Channels Not Enabled (no handling) \n");
printf (" -U <port> Enable RIGCTL/TCP; Set TCP Port for RIGCTL. (4532 on SDR++)\n");
printf (" -B <Hertz> Set RIGCTL Setmod Bandwidth in Hertz (0 - default - OFF)\n");
printf (" P25 - 7000-12000; P25 (QPSK) - 12000; NXDN48 - 4000; DMR - 7000; EDACS/PV - 12500;\n");
printf (" P25 - 7000-12000; P25 (QPSK) - 12000; NXDN48 - 7000; NXDN96: 9000; DMR - 7000; EDACS/PV - 12500;\n");
printf (" May vary based on system stregnth, etc.\n");
printf (" -t <secs> Set Trunking or Fast Scan VC/sync loss hangtime in seconds. (default = 1 second) (decimal values permitted) \n");
printf (" -t <secs> Set Trunking or Fast Scan VC/sync loss hangtime in seconds. (default = 1 second)\n");
printf ("\n");
printf (" Trunking Example TCP: dsd-fme-aero -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans\n");
printf (" Trunking Example RTL: dsd-fme-aero -fs -i rtl:0:450M:26:-2:8:0:6020 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\n");
printf (" Trunking Example TCP: dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans\n");
printf (" Trunking Example RTL: dsd-fme -fs -i rtl:0:450M:26:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\n");
printf ("\n");
exit (0);
}
@@ -1158,9 +1212,9 @@ if (opts->audio_in_type == 1)
{
opts->pulse_digi_rate_out = 24000; //rtl needs 24000 by 2 channel for DMR TDMA Stereo output
opts->pulse_digi_out_channels = 2; //minimal crackling 'may' be observed, not sure, can't test to see on DMR with RTL
fprintf (stderr, "RTL Audio Rate Out set to 24000 Khz/2 Channel \n");
// fprintf (stderr, "RTL Audio Rate Out set to 24000 Khz/2 Channel \n");
}
else fprintf (stderr, "RTL Audio Rate Out set to 48000 Khz/1 Channel \n");
// else fprintf (stderr, "RTL Audio Rate Out set to 48000 Khz/1 Channel \n");
opts->pulse_raw_rate_out = 48000;
opts->pulse_raw_out_channels = 1;
@@ -1301,13 +1355,21 @@ main (int argc, char **argv)
char versionstr[25];
mbe_printVersion (versionstr);
#ifdef LIMAZULUTWEAKS
fprintf (stderr," Digital Speech Decoder: LimaZulu Edition IV\n");
#else
fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n");
#endif
for (short int i = 1; i < 7; i++) {
fprintf (stderr,"%s\n", FM_banner[i]);
}
fprintf (stderr, "Github Build Version: %s%s \n", GIT_TAG);
fprintf (stderr,"MBElib version %s\n", versionstr);
#ifdef AERO_BUILD
fprintf (stderr, "Build Version: v2.1 Beta \n");
#else
fprintf (stderr, "Build Version: %s \n", GIT_TAG);
#endif
fprintf (stderr,"MBElib Version: %s\n", versionstr);
initOpts (&opts);
initState (&state);
@@ -1316,7 +1378,7 @@ main (int argc, char **argv)
exitflag = 0;
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:YK:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:YK:b:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
{
opterr = 0;
switch (c)
@@ -1324,23 +1386,51 @@ main (int argc, char **argv)
case 'h':
usage ();
exit (0);
case 'a':
opts.call_alert = 1;
break;
//Free'd up switches include
//Free'd up switches include: I, J, j, n, O, v, y
//all numerals have reclaimed, except for 4 and 0,1 (rc4 enforcement and single key)
//make sure to put a colon : after each if they need an argument
//or remove colon if no argument required
//NOTE: The 'K' option for single BP key has been swapped to 'b'
//'K' is now used for hexidecimal key.csv imports
//rc4 enforcement on DMR (due to missing the PI header)
case '0':
state.M = 0x21;
fprintf (stderr,"Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR)\n");
break;
//load single rc4 key
case '1':
sscanf (optarg, "%llX", &state.R);
state.RR = state.R; //put key on both sides
fprintf (stderr, "RC4 Encryption Key Value set to 0x%llX \n", state.R);
opts.unmute_encrypted_p25 = 0;
state.keyloader = 0; //turn off keyloader
break;
case 'Y': //conventional scanner mode
opts.scanner_mode = 1; //enable scanner
opts.p25_trunk = 0; //turn off trunking mode if user enabled it
break;
case 'k': //NXDN multi-key loader
case 'k': //multi-key loader (dec)
strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0';
csvKeyImport(&opts, &state);
csvKeyImportDec(&opts, &state);
state.keyloader = 1;
break;
case 'K': //multi-key loader (hex)
strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0';
csvKeyImportHex(&opts, &state);
state.keyloader = 1;
break;
@@ -1363,13 +1453,12 @@ main (int argc, char **argv)
case 'z':
sscanf (optarg, "%d", &opts.slot_preference);
opts.slot_preference--; //user inputs 1 or 2, internally we want 0 and 1
if (opts.slot_preference > 0) opts.slot_preference--; //user inputs 1 or 2, internally we want 0 and 1
if (opts.slot_preference > 1) opts.slot_preference = 1;
fprintf (stderr, "TDMA (DMR and P2) Slot Voice Preference is Slot %d. \n", opts.slot_preference+1);
break;
//Enable Audio Smoothing for Upsampled Audio
case '0':
case 'V':
state.audio_smoothing = 1;
break;
@@ -1407,28 +1496,23 @@ main (int argc, char **argv)
break;
case 'C': //new letter assignment for Channel import, flow down to allow temp numbers
case '1': //LCN to Frequency CSV Import <--> flow down to chanimport now, tell users to use a channel map for edacs
case '7': //Channel Map Frequency CSV Import
strncpy(opts.chan_in_file, optarg, 1023);
opts.chan_in_file[1023] = '\0';
csvChanImport (&opts, &state);
break;
case 'G': //new letter assignment for group import, flow down to allow temp numbers
case '2': //Group CSV Import
strncpy(opts.group_in_file, optarg, 1023);
opts.group_in_file[1023] = '\0';
csvGroupImport(&opts, &state);
break;
case 'T': //new letter assignment for trunking, flow down to allow temp numbers
case '3':
opts.p25_trunk = 1;
opts.scanner_mode = 0; //turn off scanner mode if user enabled it
break;
case 'U': //New letter assignment for RIGCTL TCP port, flow down to allow temp numbers
case '5': //RIGCTL TCP port
sscanf (optarg, "%d", &opts.rigctlportno);
if (opts.rigctlportno != 0) opts.use_rigctl = 1;
break;
@@ -1438,19 +1522,16 @@ main (int argc, char **argv)
//may change to a different return on sync times and this will matter!
case 't': //New letter assignment for Trunk Hangtime, flow down to allow temp numbers
case '6': //hangtime in seconds, default is 1;
sscanf (optarg, "%f", &opts.trunk_hangtime); //updated for float/decimal values
fprintf (stderr, "Trunking or Fast Scanner Hang Time set to: %.02f sec\n", opts.trunk_hangtime);
break;
case 'q': //New letter assignment for Reverse Mute, flow down to allow temp numbers
case '8':
opts.reverse_mute = 1;
fprintf (stderr, "Reverse Mute\n");
break;
case 'B': //New letter assignment for RIGCTL SetMod BW, flow down to allow temp numbers
case '9': //rigctl setmod bandwidth;
sscanf (optarg, "%d", &opts.setmod_bw);
if (opts.setmod_bw > 25000) opts.setmod_bw = 25000; //not too high
break;
@@ -1462,15 +1543,15 @@ main (int argc, char **argv)
state.symbolCenter = state.symbolCenter * opts.wav_interpolator;
break;
case 'v':
sscanf (optarg, "%d", &opts.verbose);
break;
// case 'v':
// sscanf (optarg, "%d", &opts.verbose);
// break;
case 'n': //disable or reclaim?
state.use_throttle = 1;
break;
// case 'n': //disable or reclaim?
// state.use_throttle = 1;
// break;
case 'K':
case 'b': //formerly Capital 'K'
sscanf (optarg, "%lld", &state.K);
if (state.K > 256)
{
@@ -1514,7 +1595,7 @@ main (int argc, char **argv)
case '4':
state.M = 1;
fprintf (stderr,"Force Privacy Key Priority over FID and SVC bits.\n");
fprintf (stderr,"Force Privacy Key over Encryption Identifiers (DMR BP and NXDN Scrambler) \n");
break;
//manually set Phase 2 TDMA WACN/SYSID/CC
@@ -1724,6 +1805,9 @@ main (int argc, char **argv)
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding only ProVoice frames.\n");
//rtl specific tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
}
else if (optarg[0] == '1')
{
@@ -1750,7 +1834,8 @@ main (int argc, char **argv)
// opts.setmod_bw = 12000;
opts.ssize = 36; //128 current default, fall back to old default on P1 only systems
opts.msize = 15; //1024 current default, fall back to old default on P1 only systems
sprintf (opts.output_name, "P25P1");
opts.use_heuristics = 1; //enable for Phase 1 only
sprintf (opts.output_name, "P25p1");
fprintf (stderr,"Decoding only P25 Phase 1 frames.\n");
}
else if (optarg[0] == 'i')
@@ -1821,8 +1906,8 @@ main (int argc, char **argv)
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
opts.frame_ysf = 0;
state.samplesPerSymbol = 10;
state.symbolCenter = 4;
state.samplesPerSymbol = 8;
state.symbolCenter = 3;
opts.mod_c4fm = 1;
opts.mod_qpsk = 0;
opts.mod_gfsk = 0;
@@ -1831,8 +1916,8 @@ main (int argc, char **argv)
state.dmr_stereo = 0;
opts.dmr_mono = 0;
// opts.setmod_bw = 12000;
sprintf (opts.output_name, "P25P2");
fprintf (stderr,"Decoding P25-P2 frames C4FM or OP25 Symbol Captures!\n");
sprintf (opts.output_name, "P25p2");
fprintf (stderr,"Decoding 6000 sps P25p2 frames only!\n");
}
else if (optarg[0] == 's')
{
@@ -1928,15 +2013,15 @@ main (int argc, char **argv)
opts.mod_qpsk = 0;
opts.mod_gfsk = 0; //
state.rf_mod = 0; //
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
opts.dmr_mono = 1;
opts.dmr_stereo = 0;
opts.pulse_digi_rate_out = 24000;
opts.pulse_digi_out_channels = 2;
opts.dmr_mono = 0;
opts.dmr_stereo = 1;
state.dmr_stereo = 0; //0
// opts.setmod_bw = 7000;
sprintf (opts.output_name, "DMR Mono");
fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo '-fs' or XDMA '-ft' is highly encouraged.\n");
sprintf (opts.output_name, "DMR Stereo");
fprintf (stderr,"-fr / DMR Mono switch has been deprecated.\n");
fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n");
}
else if (optarg[0] == 'm')
@@ -2011,7 +2096,7 @@ main (int argc, char **argv)
state.samplesPerSymbol = 8;
state.symbolCenter = 3;
// opts.setmod_bw = 12000;
fprintf (stderr,"Enabling 6000 sps P25p2 CQPSK.\n");
fprintf (stderr,"Enabling 6000 sps P25p2 QPSK.\n");
}
//test
else if (optarg[0] == '3')
@@ -2166,7 +2251,6 @@ main (int argc, char **argv)
if (opts.use_rigctl == 1)
{
// opts.rigctl_sockfd = Connect(opts.rigctlhostname, opts.rigctlportno);
opts.rigctl_sockfd = Connect(opts.rigctlhostname, opts.rigctlportno);
if (opts.rigctl_sockfd != 0) opts.use_rigctl = 1;
else
@@ -2209,12 +2293,12 @@ main (int argc, char **argv)
int bw = 0;
bw = atoi (curr);
//check for proper values (6,8,12,24)
if (bw == 6 || bw == 8 || bw == 12 || bw == 24)
if (bw == 4 || bw == 6 || bw == 8 || bw == 12 || bw == 16 || bw == 24) //testing 4 and 16 as well for weak and/or nxdn48 systems
{
opts.rtl_bandwidth = bw;
}
else
opts.rtl_bandwidth = 12; //safe default
opts.rtl_bandwidth = 12; //safe default -- provides best performance on most systems
}
else goto RTLEND;
@@ -2267,7 +2351,7 @@ main (int argc, char **argv)
int fmt;
int speed = 48000;
//NOTE: Might can use this code in an ifdef to be able to use /dev/audio under padsp in Linux
//NOTE: Both /dev/audio AND /dev/dsp randomly open multiple input streams in Linux under padsp wrapper
if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
{
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
@@ -2406,58 +2490,60 @@ main (int argc, char **argv)
opts.playoffset = 0;
opts.playoffsetR = 0;
opts.delay = 0;
if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
{
openWavOutFile (&opts, &state);
}
//open wav file should be handled directly by the -w switch now
// if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
// {
// openWavOutFile (&opts, &state);
// }
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
if (opts.audio_out_type == 0) openPulseOutput(&opts);
if (opts.audio_out_type == 5) openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
}
//this particular if-elseif-else could be rewritten to be a lot neater and simpler
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
{
opts.split = 1;
opts.playoffset = 0;
opts.playoffsetR = 0;
opts.delay = 0;
if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
{
openWavOutFile (&opts, &state);
}
else
{
openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
}
//open wav file should be handled directly by the -w switch now
// if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
// openWavOutFile (&opts, &state);
// else
openAudioInDevice (&opts);
fprintf (stderr,"Press CTRL + C to close.\n");
// fprintf (stderr,"Press CTRL + C to close.\n");
}
else
else
{
opts.split = 0;
opts.playoffset = 25;
opts.playoffsetR = 25;
opts.playoffset = 0; //not sure what the playoffset actually does for us
opts.playoffsetR = 0;
opts.delay = 0;
openAudioInDevice (&opts);
opts.audio_out_fd = opts.audio_in_fd;
// opts.audio_out_fd = opts.audio_in_fd; //not sure that this really does much anymore, other than cause problems
}
if (opts.playfiles == 1)
if (opts.playfiles == 1)
{
state.aout_gain = 25; //BUGFIX: No audio output when playing back .amb/.imb files
playMbeFiles (&opts, &state, argc, argv);
}
else
else
{
liveScanner (&opts, &state);
}
cleanupAndExit (&opts, &state);
cleanupAndExit (&opts, &state);
return (0);
return (0);
}

View File

@@ -17,6 +17,56 @@
#include "dsd.h"
//test for potential clashing with other key loading mechanisms (bp key loading on tgid, nxdn key loading, etc)
void keyring(dsd_opts * opts, dsd_state * state)
{
//keys now loaded from csv files with the -K key.csv file (capital K)
if (state->currentslot == 0)
state->R = state->rkey_array[state->payload_keyid];
if (state->currentslot == 1)
state->RR = state->rkey_array[state->payload_keyidR];
}
void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[])
{
int i, j, count;
uint8_t t, b;
//init Sbox
uint8_t S[256];
for(int i = 0; i < 256; i++) S[i] = i;
//Key Scheduling
j = 0;
for(i = 0; i < 256; i++)
{
j = (j + S[i] + key[i % keylength]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
}
//Drop Bytes and Cipher Byte XOR
i = j = 0;
for(count = 0; count < (messagelength + drop); count++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
b = S[(S[i] + S[j]) % 256];
//return mbe payload byte here
if (count >= drop)
plain[count - drop] = b^cipher[count - drop];
}
}
int Pr[256] = {
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
@@ -140,6 +190,13 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
unsigned long long int k;
int x;
//these conditions should ensure no clashing with the BP/HBP/Scrambler key loading machanisms already coded in
if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->keyloader == 1)
keyring (opts, state);
if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->keyloader == 1)
keyring (opts, state);
//24-bit TG to 16-bit hash
uint32_t hash = 0;
uint8_t hash_bits[24];
@@ -192,7 +249,73 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
mbe_demodulateImbe7200x4400Data (imbe_fr);
state->errs2 = mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
//P25p1 RC4 Handling
if (state->payload_algid == 0xAA && state->R != 0)
{
uint8_t cipher[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
// load valid MI from state->payload_miP
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
// if (state->p25vc == 0)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, "\n RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// }
//load imbe_d into imbe_cipher octets
int z = 0;
for (i = 0; i < 11; i++)
{
cipher[i] = 0;
plain[i] = 0;
for (short int j = 0; j < 8; j++)
{
cipher[i] = cipher[i] << 1;
cipher[i] = cipher[i] + imbe_d[z];
imbe_d[z] = 0;
z++;
}
}
RC4(state->dropL, 13, 11, rckey, cipher, plain);
state->dropL += 11;
z = 0;
for (short p = 0; p < 11; p++)
{
for (short o = 0; o < 8; o++)
{
imbe_d[z] = (plain[p] & 0x80) >> 7;
plain[p] = plain[p] << 1;
z++;
}
}
}
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
@@ -299,8 +422,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//EXPERIMENTAL!!
//load basic privacy key number from array by the tg value (if not forced)
//currently only Moto BP and Hytera 10 Char BP (converted to decimal)
if (state->M == 0)
//currently only Moto BP and Hytera 10 Char BP
if (state->M == 0 && state->payload_algid == 0)
{
//see if we need to hash a value larger than 16-bits
hash = state->lasttg & 0xFFFFFF;
@@ -400,6 +523,155 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
state->DMRvcL++;
}
//DMR RC4, Slot 1
if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0)
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00}; // <- MI
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
rckey[5] = ((state->payload_mi & 0xFF000000) >> 24);
rckey[6] = ((state->payload_mi & 0xFF0000) >> 16);
rckey[7] = ((state->payload_mi & 0xFF00) >> 8);
rckey[8] = ((state->payload_mi & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 9; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropL, 9, 7, rckey, cipher, plain);
state->dropL += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
//P25p2 RC4 Handling, VCH 0
if (state->currentslot == 0 && state->payload_algid == 0xAA && state->R != 0 && ((state->synctype == 35) || (state->synctype == 36)))
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
// load valid MI from state->payload_miP
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropL, 13, 7, rckey, cipher, plain);
state->dropL += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
@@ -429,8 +701,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//EXPERIMENTAL!!
//load basic privacy key number from array by the tg value (if not forced)
//currently only Moto BP and Hytera 10 Char BP (converted to decimal)
if (state->M == 0)
//currently only Moto BP and Hytera 10 Char BP
if (state->M == 0 && state->payload_algidR == 0)
{
//see if we need to hash a value larger than 16-bits
hash = state->lasttgR & 0xFFFFFF;
@@ -530,6 +802,155 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
state->DMRvcR++;
}
//DMR RC4, Slot 2
if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00}; // <- MI
//easier to manually load up rather than make a loop
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
rckey[1] = ((state->RR & 0xFF000000) >> 24);
rckey[2] = ((state->RR & 0xFF0000) >> 16);
rckey[3] = ((state->RR & 0xFF00) >> 8);
rckey[4] = ((state->RR & 0xFF) >> 0);
rckey[5] = ((state->payload_miR & 0xFF000000) >> 24);
rckey[6] = ((state->payload_miR & 0xFF0000) >> 16);
rckey[7] = ((state->payload_miR & 0xFF00) >> 8);
rckey[8] = ((state->payload_miR & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 9; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropR, 9, 7, rckey, cipher, plain);
state->dropR += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
//P25p2 RC4 Handling, VCH 1
if (state->currentslot == 1 && state->payload_algidR == 0xAA && state->RR != 0 && ((state->synctype == 35) || (state->synctype == 36)))
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
rckey[1] = ((state->RR & 0xFF000000) >> 24);
rckey[2] = ((state->RR & 0xFF0000) >> 16);
rckey[3] = ((state->RR & 0xFF00) >> 8);
rckey[4] = ((state->RR & 0xFF) >> 0);
//state->payload_miN for VCH1/slot 2
rckey[5] = ((state->payload_miN & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miN & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miN & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miN & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miN & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miN & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miN & 0xFF00) >> 8);
rckey[12] = ((state->payload_miN & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropR, 13, 7, rckey, cipher, plain);
state->dropR += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR,
ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
@@ -584,7 +1005,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
else state->dmr_encL = 0;
//second checkdown for P25-2 WACN, SYSID, and CC set
//check for available R key
if (state->R != 0) state->dmr_encL = 0;
//second checkdown for P25p2 WACN, SYSID, and CC set
if (state->synctype == 35 || state->synctype == 36)
{
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
@@ -613,7 +1037,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
#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
//OSS Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16)
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstR == 16 || state->dmrburstR == 21) )
{
opts->audio_out = 0;
preempt = 1;
@@ -651,7 +1075,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
else state->dmr_encR = 0;
//second checkdown for P25-2 WACN, SYSID, and CC set
//check for available RR key
if (state->RR != 0) state->dmr_encR = 0;
//second checkdown for P25p2 WACN, SYSID, and CC set
if (state->synctype == 35 || state->synctype == 36)
{
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
@@ -680,7 +1107,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
#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
//OSS Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstL == 16)
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstL == 16 || state->dmrburstL == 21) )
{
opts->audio_out = 0;
preempt = 1;

View File

@@ -12,20 +12,12 @@
#include "dsd.h"
#include "git_ver.h"
//UDP Remote
#include <arpa/inet.h>
// #include <sys/socket.h>
#include <netinet/in.h>
#define BSIZE 999
#define UDP_BUFLEN 5 //maximum UDP buffer length
#define SRV_IP "127.0.0.1" //IP
#define UDP_PORT 6020 //UDP port
int handle; //for UDP
unsigned short udp_port = UDP_PORT;
char data[UDP_BUFLEN] = {0};
struct sockaddr_in address;
uint32_t temp_freq = -1;
//
@@ -49,19 +41,6 @@ int i = 0;
char versionstr[25];
unsigned long long int call_matrix[33][6];
#ifdef LIMAZULUTWEAKS
char * FM_bannerN[9] = {
" ",
" ██████╗ ██████╗██████╗ ███╗ ███████╗",
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
" ██║ ██║╚█████╗ ██║ ██║ ███║ ███╔═╝",
" ██║ ██║ ╚═══██╗██║ ██║ Lima ███║ ██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝ Zulu ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ Edition III ╚═══════╝╚══════╝",
" ",
" "
};
#else
char * FM_bannerN[9] = {
" ",
" ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ ",
@@ -73,8 +52,6 @@ char * FM_bannerN[9] = {
" ",
" "
};
#endif
char * SyncTypes[44] = {
"P25P1",
@@ -87,10 +64,10 @@ char * SyncTypes[44] = {
"DSTAR",
"NXDN VOICE",
"NXDN VOICE",
"DMR ", //10
"DMR ",
"DMR ",
"DMR ",
"DMR", //10
"DMR",
"DMR",
"DMR",
"EDACS/PV",
"EDACS/PV",
"NXDN VOICE", //DATA
@@ -109,9 +86,9 @@ char * SyncTypes[44] = {
"NXDN",
"YSF", //30
"YSF",
"DMR ",
"DMR ",
"DMR ",
"DMR",
"DMR",
"DMR",
"P25P2",
"P25P2",
"EDACS/PV", //37
@@ -137,35 +114,35 @@ char * DMRBusrtTypes[32] = {
"R-S ERR ",
"CRC ERR ",
"NULL ",
"Voice ",
"VOICE",
" ",
"INIT ",
"INIT ",
"MAC PTT", //20
"MAC ACTIVE", //21
"MAC HANGTIME", //22
"MAC PTT END", //23
"MAC IDLE", //24
"PTT", //20 MAC
"VOICE", //21 MAC_ACTIVE
"HANGTIME", //22 MAC
"PTT END", //23 MAC
"IDLE", //24 MAC
"HDU",
"VOICE LDU", //26
"VOICE LDU",
"TDU/TDULC",
"VOICE", //26 LDU1
"VOICE", //27 LDU2
"TDU/LC",
"TSBK",
"MAC SIGNAL",
"MAC SIGNAL"
"SIGNAL", //MAC_SIGNAL
"SIGNAL" //MAC_SIGNAL
};
#ifdef TONES //NOTE: This option is purely for the precompiled version that gets distributed, not other user Cygwin builds
void beeper (dsd_opts * opts, dsd_state * state, int type)
{
FILE *beep;
char wav_name[1024] = {0};
if (opts->pulse_digi_rate_out == 8000) strncpy(wav_name, "tone8.wav", 1023);
if (opts->pulse_digi_rate_out == 48000) strncpy(wav_name, "tone48.wav", 1023);
if (opts->pulse_digi_rate_out == 24000) strncpy(wav_name, "tone24.wav", 1023);
if (opts->audio_out_type == 5) strncpy(wav_name, "tone48.wav", 1023);
wav_name[1023] = '\0';
struct stat stat_buf;
if (stat(wav_name, &stat_buf) == 0)
@@ -214,6 +191,62 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
}
#else
void beeper (dsd_opts * opts, dsd_state * state, int type)
{
FILE *beep;
char wav_name[1024] = {0};
if (opts->pulse_digi_rate_out == 8000) strncpy(wav_name, "/usr/share/tone8.wav", 1023);
if (opts->pulse_digi_rate_out == 48000) strncpy(wav_name, "/usr/share/tone48.wav", 1023);
if (opts->pulse_digi_rate_out == 24000) strncpy(wav_name, "/usr/share/tone24.wav", 1023);
if (opts->audio_out_type == 5) strncpy(wav_name, "/usr/share/tone24.wav", 1023);
wav_name[1023] = '\0';
struct stat stat_buf;
if (stat(wav_name, &stat_buf) == 0)
{
beep = fopen (wav_name, "ro");
uint8_t buf[1024];
memset (buf, 0, sizeof(buf));
short blip = 0;
int loop = 1;
while (loop == 1)
{
fread(buf, sizeof(buf), 1, beep);
if ( feof (beep) )
{
loop = 0;
}
if (loop == 1)
{
//only beep on R if dmr_stereo is active and slot 2, else beep on L
if (type == 0 && opts->dmr_stereo == 1 && opts->audio_out == 1)
{
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
//fprintf (stderr, "BEEP 0 24\n");
}
if (type == 1 && opts->dmr_stereo == 1 && opts->audio_out == 1)
{
pa_simple_write(opts->pulse_digi_dev_outR, buf, sizeof(buf), NULL);
//fprintf (stderr, "BEEP 1 24\n");
}
if (opts->dmr_stereo == 0 && opts->audio_out == 1)
{
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
//fprintf (stderr, "BEEP 0 8\n");
}
}
}
fclose (beep);
}
}
#endif
char * getDateN(void) {
char datename[80]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char * curr2;
@@ -299,15 +332,15 @@ char *choices[] = {
"Decode Legacy Auto**",
"Decode XDMA (P25 and DMR BS/MS)",
"Decode D-STAR*",
"Decode P25-P1*",
"Decode P25p1*",
"Decode EDACS/PV",
"Decode DMR Mono*",
"Decode P25p2 ",
"Decode dPMR",
"Decode NXDN48",
"Decode NXDN96",
"Decode DMR Stereo", //was X2-TDMA*
"Toggle Signal Inversion",
"Privacy Key Entry",
"Key Entry",
"Reset Call History",
"Toggle Payloads to Console",
"Manually Set P2 Parameters", //16
@@ -430,6 +463,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
closePulseInput(opts);
}
if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
rtl_clean_queue();
#endif
}
if (opts->audio_in_type == 8) //close TCP input SF file so we don't buffer audio while not decoding
{
sf_close(opts->tcp_file_in);
@@ -445,8 +485,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
//zero out to fix call history 'scrolling' bug when changing decoding types
state->nxdn_last_tg = 0;
state->nxdn_last_ran = 0;
state->nxdn_last_rid = 0;
state->nxdn_last_ran = -1; //0
state->nxdn_last_rid = 0; //0
WINDOW *menu_win;
WINDOW *test_win;
@@ -622,10 +662,6 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
#ifdef USE_RTLSDR
//could also benefit from having some control aside from UDP remote
//BUG: When squelch enabled, all processing halts, no more ncursesprinter until squelch broken
//make another submenu to control these values if tests go well
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter RTL Device Index Number");
@@ -635,7 +671,6 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
wscanw(entry_win, "%d", &opts->rtl_dev_index);
noecho();
//this is NOT scanning (or printing) in the variable for some reason...why?
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter RTL Device PPM Error");
@@ -644,21 +679,19 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
refresh();
wscanw(entry_win, "%d", &opts->rtlsdr_ppm_error);
noecho();
//opts->rtlsdr_ppm_error = -1; //hard set override for testing
//apparently, scanning in an lld nukes later box entries for some reason
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter Frequency in Hz (851.8 MHz is 851800000 Hz) ");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq); //ld, or lld?
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq);
noecho();
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter VFO Bandwidth (6, 8, 12, 16, 24, 48)");
mvwprintw(entry_win, 2, 2, " Enter BW (8, 12, 24, 48)(12 Recommended)");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
@@ -667,7 +700,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter RTL Gain Value (0-49) (0 = Auto Gain)");
mvwprintw(entry_win, 2, 2, " Enter RTL Gain Value (0-49) (0 = AGC)");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
@@ -676,22 +709,17 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter RTL UDP Remote Port (Default = 6020)");
mvwprintw(entry_win, 2, 2, " Enter RTL UDP Port - Optional (Default = 0)");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &opts->rtl_udp_port);
noecho();
if (opts->rtl_udp_port == 0)
{
opts->rtl_udp_port = 6020;
}
entry_win = newwin(8, WIDTH+22, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Enter RTL Device Squelch Level or Enter 0");
mvwprintw(entry_win, 3, 2, " WARNING! Renders Terminal Unresponsive When No Signal!");
mvwprintw(entry_win, 4, 3, " ");
mvwprintw(entry_win, 2, 2, " Enter RTL RMS Squelch Level (NXDN/dPMR only)");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &opts->rtl_squelch_level);
@@ -702,11 +730,11 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
mvwprintw(entry_win, 2, 2, " Starting RTL Input. Cannot Release/Stop Until Exit.");
mvwprintw(entry_win, 4, 2, " RTL Frequency: %d Hz", opts->rtlsdr_center_freq);
mvwprintw(entry_win, 5, 2, " RTL Device Index Number: %d", opts->rtl_dev_index);
mvwprintw(entry_win, 6, 2, " RTL Device VFO Bandwidth: %d kHz", opts->rtl_bandwidth);
mvwprintw(entry_win, 6, 2, " RTL Device Bandwidth: %d kHz", opts->rtl_bandwidth);
mvwprintw(entry_win, 7, 2, " RTL Device Gain: %d", opts->rtl_gain_value);
mvwprintw(entry_win, 8, 2, " RTL Device UDP Port: %d", opts->rtl_udp_port);
mvwprintw(entry_win, 9, 2, " RTL Device PPM: %d", opts->rtlsdr_ppm_error);
mvwprintw(entry_win, 10, 2, " RTL Device Squelch: %d", opts->rtl_squelch_level);
mvwprintw(entry_win, 10, 2, " RTL RMS Squelch: %d", opts->rtl_squelch_level);
mvwprintw(entry_win, 12, 2, " Are You Sure?");
mvwprintw(entry_win, 13, 2, " 1 = Yes, 2 = No ");
mvwprintw(entry_win, 14, 3, " ");
@@ -718,6 +746,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
refresh();
//works well, but can't release dongle later, so its a one way trip until exit
//TODO: Write function to release the dongle -- call cleanup_rtlsdr_stream()
if (confirm == 1)
{
opts->audio_in_type = 3; //RTL input, only set this on confirm
@@ -728,7 +757,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
}
if (choicec == 7) //RTL UDP Retune
if (choicec == 7) //RTL DEV Retune
{
//read in new rtl frequency
#ifdef USE_RTLSDR
@@ -738,14 +767,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq); //ld, or lld?
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq);
noecho();
//do the thing with the thing
data[0] = 0;
data[1] = opts->rtlsdr_center_freq & 0xFF;
data[2] = (opts->rtlsdr_center_freq >> 8) & 0xFF;
data[3] = (opts->rtlsdr_center_freq >> 16) & 0xFF;
data[4] = (opts->rtlsdr_center_freq >> 24) & 0xFF;
temp_freq = opts->rtlsdr_center_freq;
#endif
@@ -1068,15 +1091,18 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->payload_keyid = 0;
state->payload_keyidR = 0;
short int option = 0;
entry_win = newwin(11, WIDTH+6, starty+10, startx+10);
entry_win = newwin(14, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "Key Type Selection");
mvwprintw(entry_win, 3, 2, " ");
mvwprintw(entry_win, 4, 2, "1 - Basic Privacy ");
mvwprintw(entry_win, 5, 2, "2 - **tera Privacy ");
mvwprintw(entry_win, 6, 2, "3 - NXDN/dPMR Scrambler ");
mvwprintw(entry_win, 7, 2, "4 - Force Key Priority ");
mvwprintw(entry_win, 8, 3, " ");
mvwprintw(entry_win, 7, 2, "4 - Force BP/Scr Key Priority ");
mvwprintw(entry_win, 8, 3, "-------------------------------- ");
mvwprintw(entry_win, 9, 2, "5 - RC4 Key ");
mvwprintw(entry_win, 10, 2, "6 - Force DMR RC4 Priority/LE ");
mvwprintw(entry_win, 11, 3, " ");
echo();
refresh();
wscanw(entry_win, "%hd", &option); //%d
@@ -1088,16 +1114,15 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->K = 0;
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "DMRA Privacy Key Number (DEC):");
mvwprintw(entry_win, 2, 2, "Basic Privacy Key Number (DEC):");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%lld", &state->K);
noecho();
if (state->K > 255)
{
state->K = 255;
}
if (state->K > 255) state->K = 255;
state->keyloader = 0; //turn off keyloader
}
if (option == 2)
{
@@ -1148,6 +1173,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
wscanw(entry_win, "%llX", &state->K4);
noecho();
state->keyloader = 0; //turn off keyloader
}
if (option == 3)
{
@@ -1160,20 +1186,49 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
refresh();
wscanw(entry_win, "%lld", &state->R);
noecho();
if (state->K > 0x7FFF)
{
state->K = 0x7FFF;
}
if (state->R > 0x7FFF) state->R = 0x7FFF;
state->keyloader = 0; //turn off keyloader
}
//toggle enforcement of privacy key over enc bit set on traffic
//toggle enforcement of basic privacy key over enc bit set on traffic
if (option == 4)
{
if (state->M == 0)
if (state->M == 1 || state->M == 0x21)
{
state->M = 1;
state->M = 0;
}
else state->M = 0;
else state->M = 1;
}
if (option == 5)
{
state->R = 0;
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "RC4 Key Value (HEX):");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%llX", &state->R);
noecho();
if (state->R > 0xFFFFFFFFFF)
{
state->R = 0xFFFFFFFFFF;
}
state->RR = state->R; //assign for both slots
state->keyloader = 0; //turn off keyloader
}
//toggle enforcement of rc4 key over missing pi header/le on DMR
if (option == 6)
{
if (state->M == 1 || state->M == 0x21)
{
state->M = 0;
}
else state->M = 0x21;
}
if (state->K == 0 && state->K1 == 0 && state->K2 == 0 && state->K3 == 0 && state->K4 == 0)
{
opts->dmr_mute_encL = 1;
@@ -1186,7 +1241,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 2)
{
//setup Auto parameters--default ones
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (opts->output_name, "Legacy Auto");
@@ -1216,7 +1271,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 6)
{
//ProVoice Specifics
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 5;
state->symbolCenter = 2;
sprintf (opts->output_name, "EDACS/PV");
@@ -1244,7 +1299,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 4)
{
//DSTAR
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (opts->output_name, "D-STAR");
@@ -1274,13 +1329,19 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 5)
{
//P25 P1
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
opts->use_heuristics = 1;
if (opts->use_heuristics == 1)
{
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
}
opts->frame_p25p1 = 1;
opts->frame_p25p2 = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
state->rf_mod = 0;
sprintf (opts->output_name, "P25P1");
sprintf (opts->output_name, "P25p1");
opts->dmr_mono = 0;
opts->dmr_stereo = 0; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
@@ -1306,7 +1367,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 3)
{
//XDMA Stereo P25 1, 2, and DMR
resetState (state); //use sparingly, seems to cause issue when switching back to other formats
// resetState (state); //use sparingly, seems to cause issue when switching back to other formats
if (opts->use_heuristics == 1)
{
initialize_p25_heuristics(&state->p25_heuristics);
initialize_p25_heuristics(&state->inv_p25_heuristics);
}
opts->use_heuristics = 0;
opts->frame_dmr = 1;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
@@ -1334,24 +1401,22 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
}
if (choice == 7)
{
//set legacy DMR settings
resetState (state); //use sparingly, seems to cause issue when switching back to other formats
opts->frame_dmr = 1;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
state->rf_mod = 0;
sprintf (opts->output_name, "DMR Mono");
opts->dmr_mono = 1;
opts->dmr_stereo = 0; //this value is the end user option
// resetState (state); //use sparingly, seems to cause issue when switching back to other formats
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
sprintf (opts->output_name, "P25p2");
opts->dmr_mono = 0;
opts->dmr_stereo = 1; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
opts->pulse_digi_rate_out = 48000;
opts->pulse_digi_out_channels = 1;
opts->pulse_digi_rate_out = 24000;
opts->pulse_digi_out_channels = 2;
opts->frame_dmr = 0;
opts->frame_dstar = 0;
opts->frame_x2tdma = 0;
opts->frame_p25p1 = 0;
opts->frame_p25p2 = 1;
opts->frame_nxdn48 = 0;
opts->frame_nxdn96 = 0;
//opts->frame_dmr = 0;
opts->frame_dpmr = 0;
opts->frame_provoice = 0;
opts->frame_ysf = 0;
@@ -1364,7 +1429,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 8)
{
//dPMR
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 20;
state->symbolCenter = 10;
sprintf (opts->output_name, "dPMR");
@@ -1392,7 +1457,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 9)
{
//NXDN48
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
opts->frame_nxdn48 = 1;
state->samplesPerSymbol = 20;
state->symbolCenter = 10;
@@ -1421,7 +1486,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 10)
{
//NXDN96
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (opts->output_name, "NXDN96");
@@ -1448,7 +1513,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (choice == 11)
{
//Decode DMR Stereo (was X2-TDMA)
resetState (state); //use sparingly, may cause memory leak
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
// sprintf (opts->output_name, "X2-TDMA");
@@ -1676,18 +1741,25 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
{
openPulseInput(opts);
}
#ifdef USE_RTLSDR
//fix location of this statement to inside the if statement and add conditions
if (opts->audio_in_type == 3) //open rtl input if it is the specified input method
{
ncursesPrinter (opts, state); //run one rep to clear menu boxes out
#ifdef USE_RTLSDR
if (opts->rtl_started == 0)
{
opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again
open_rtlsdr_stream(opts);
}
rtl_clean_queue();
reset_dibit_buffer(state); //test and observe for any random issues, disable if needed
#elif AERO_BUILD
opts->audio_out_type = 3; //hopefully the audio stream is still/already open
#else
opts->audio_out_type = 0; //need to see if we need to open pulseoutput as well here?
openPulseOutput (opts);
#endif
}
#endif
if (opts->audio_in_type == 8) //re-open TCP input 'file'
{
@@ -1718,11 +1790,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
c = getch(); //
}
//use rtl_udp_tune
//use rtl_dev_tune
#ifdef USE_RTLSDR
if (temp_freq == opts->rtlsdr_center_freq)
{
rtl_udp_tune (opts, state, temp_freq);
rtl_dev_tune (opts, temp_freq);
temp_freq = -1;
}
#endif
@@ -2086,14 +2158,29 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", GIT_TAG);
// printw ("| Digital Speech Decoder: Florida Man Edition - zDEV %s \n", "v2.0.0-100-gae58fab Win32");
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.1 Beta");
printw ("------------------------------------------------------------------------------\n");
}
#elif LIMAZULUTWEAKS
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: LimaZulu Edition V: The Empire Strikes Back \n");
printw ("------------------------------------------------------------------------------\n");
}
#elif ZDEV_BUILD
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - zDEV %s \n", GIT_TAG);
printw ("------------------------------------------------------------------------------\n");
}
#else
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - zDEV %s \n", GIT_TAG);
printw ("| Digital Speech Decoder: Florida Man Edition - Main %s \n", GIT_TAG);
printw ("------------------------------------------------------------------------------\n");
}
#endif
if (opts->ncurses_compact == 0)
@@ -2106,11 +2193,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (i == 2) printw (" 'q' to Quit ");
if (i == 4) printw (" MBElib %s", versionstr);
#ifdef AERO_BUILD
if (i == 5) printw (" %s ", "Aero Win32");
if (i == 6) printw (" %s \n", GIT_TAG); //don't have the git dev package on my cygwin32 bit environment and can't get it now (32-bit no longer supported)
// if (i == 6) printw (" v2.0.0-100-gae58fab \n"); //put appropriate version in here later, or find the GIT_TAG package (git_revision) to build in cygwin
#else
if (i == 5) printw (" %s ", "zDEV BUILD");
if (i == 5) printw (" %s ", "Aero Build");
if (i == 6) printw (" v2.1 Beta \n");
#elif ZDEV_BUILD
if (i == 5) printw (" %s ", "zDEV Build");
if (i == 6) printw (" %s \n", GIT_TAG);
#else
if (i == 5) printw (" %s ", "Main Build");
if (i == 6) printw (" %s \n", GIT_TAG);
#endif
else printw ("\n");
@@ -2119,6 +2208,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4));
}
//fix color/pair issue when compact and trunking enabled
if (opts->ncurses_compact == 1 && opts->p25_trunk == 1) attron(COLOR_PAIR(4));
printw ("--Input Output----------------------------------------------------------------\n");
if (opts->audio_in_type == 0)
{
@@ -2126,7 +2218,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (opts->audio_in_type == 5)
{
printw ("| OSS Audio Input: [%2i] kHz [1] Channel\n", SAMPLE_RATE_IN);
printw ("| OSS Audio Input: [%2i] kHz [1] Channel\n", SAMPLE_RATE_IN/1000);
}
if (opts->audio_in_type == 4)
{
@@ -2149,12 +2241,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (opts->audio_in_type == 3)
{
printw ("| RTL2838UHIDIR Device #[%d]", opts->rtl_dev_index);
printw (" Gain [%i] dB -", opts->rtl_gain_value);
printw (" Squelch [%i]", opts->rtl_squelch_level);
printw (" VFO [%i] kHz\n", opts->rtl_bandwidth);
printw ("| Freq: [%d] Hz", opts->rtlsdr_center_freq); //%lld
printw (" - Tuning available on UDP Port [%i]\n", opts->rtl_udp_port);
printw ("| RTL: %d;", opts->rtl_dev_index);
if (opts->rtl_gain_value == 0)
printw (" Gain: AGC;");
else
printw (" Gain: %idB;", opts->rtl_gain_value);
printw (" PPM: %i;", opts->rtlsdr_ppm_error);
printw (" SQ: %i;", opts->rtl_squelch_level);
printw (" RMS: %04i;", opts->rtl_rms);
printw (" BW: %i kHz;", opts->rtl_bandwidth);
printw (" FRQ: %i;", opts->rtlsdr_center_freq);
if (opts->rtl_udp_port != 0) printw ("\n| External Tuning on UDP Port: %i", opts->rtl_udp_port);
printw ("\n");
}
if (opts->audio_out_type == 0)
{
@@ -2164,7 +2262,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (opts->audio_out_type == 5)
{
printw ("| OSS Audio Output: [%2i] kHz [1] Channel", SAMPLE_RATE_IN);
printw ("| OSS Audio Output: [%2i] kHz [1] Channel", SAMPLE_RATE_OUT/1000);
if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n");
}
@@ -2246,6 +2344,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->K1 != 0) printw ("| Forcing Key Priority -- tera BP Key: %016llX \n", state->K1);
if (state->K != 0 && state->K1 != 0) printw ("| Warning! Multiple DMR Key Types Loaded! \n"); //warning may not be required
}
if (state->M == 0x21)
{
if (state->R != 0) printw ("| Forcing Key Priority -- RC4 Key: %010llX \n", state->R);
}
if (opts->scanner_mode == 1)
{
printw ("| Fast Scan Mode Enabled ");
@@ -2264,11 +2366,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->mod_qpsk == 1) level = (int) state->max / 328; //test values here
reset = 1;
}
if (state->carrier == 0 && opts->reset_state == 1 && reset == 1)
{
resetState (state);
reset = 0;
}
printw ("--Audio Decode----------------------------------------------------------------\n");
printw ("| Demod/Rate: ");
@@ -2346,8 +2443,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("| ");
#ifdef LIMAZULUTWEAKS
if (idas == 0) printw ("NXDN - RAN: [%02d] ", state->nxdn_last_ran);
if (idas == 1) printw ("IDAS - Area: [%02d] ", state->nxdn_last_ran);
#else
if (idas == 0) printw ("NXDN - RAN: [%02d] ", rn);
if (idas == 1) printw ("IDAS - Area: [%02d] ", rn);
#endif
if (state->nxdn_location_site_code != 0)
{
printw ("Cat: [%s] ", state->nxdn_location_category);
@@ -2549,7 +2651,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
#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
//
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && ( state->dmrburstL == 16 || state->dmrburstL == 21) && (state->dmrburstR == 16 || state->dmrburstR == 21)) printw ("*M*");
//
#endif
@@ -2585,7 +2687,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstL == 16 && state->payload_algid > 0 && (state->dmr_so & 0xCF) == 0x40)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algid, state->payload_keyid, state->payload_mi);
printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algid, state->payload_keyid, state->payload_mi);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@@ -2594,7 +2696,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstL > 19 && state->payload_algid > 0 && state->payload_algid != 0x80)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algid, state->payload_keyid, state->payload_miP);
printw ("ALG: 0x%02X KEY: 0x%04X MI: 0x%016llX ", state->payload_algid, state->payload_keyid, state->payload_miP);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@@ -2602,7 +2704,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->payload_algid == 0xAA || state->payload_algid == 0x21)
{
attron(COLOR_PAIR(1));
printw("ADP-RC4");
printw("RC4 ");
if (state->R != 0) { printw("Key: %010llX ", state->R); }
attron(COLOR_PAIR(3));
}
if (state->payload_algid == 0x81 || state->payload_algid == 0x22)
@@ -2750,7 +2853,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("%s ", DMRBusrtTypes[state->dmrburstR]);
#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
//
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && ( state->dmrburstL == 16 || state->dmrburstL == 21) && (state->dmrburstR == 16 || state->dmrburstR == 21) ) printw ("*M*");
//
#endif
printw ("\n");
@@ -2783,7 +2886,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstR == 16 && state->payload_algidR > 0 && (state->dmr_soR & 0xCF) == 0x40)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algidR, state->payload_keyidR, state->payload_miR);
printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algidR, state->payload_keyidR, state->payload_miR);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@@ -2791,14 +2894,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstR > 19 && state->payload_algidR > 0 && state->payload_algidR != 0x80)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algidR, state->payload_keyidR, state->payload_miN);
printw ("ALG: 0x%02X KEY: 0x%04X MI: 0x%016llX ", state->payload_algidR, state->payload_keyidR, state->payload_miN);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0xAA || state->payload_algidR == 0x21)
{
attron(COLOR_PAIR(1));
printw("ADP-RC4");
printw("RC4 ");
if (state->RR != 0) { printw("Key: %010llX ", state->RR); }
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0x81 || state->payload_algidR == 0x22)
@@ -3083,7 +3187,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//only print if a valid time was assigned to the matrix, and not EDACS/PV, and source is not zero
if ( ((time(NULL) - call_matrix[9-j][5]) < 999999) && call_matrix[9-j][0] != 14 && call_matrix[9-j][0] != 15 && call_matrix[9-j][0] != 37 && call_matrix[9-j][0] != 38 && call_matrix[9-j][2] != 0) //
{
printw ("| %s ", SyncTypes[call_matrix[9-j][0]]);
// printw ("| %s ", SyncTypes[call_matrix[9-j][0]]); //sync type
printw ("| ");
printw ("%s ", getDateC(call_matrix[9-j][5]) );
printw ("%s ", getTimeC(call_matrix[9-j][5]) );
if (lls == 28 || lls == 29)
{
if (idas == 0) printw ("RAN [%02lld] ", call_matrix[9-j][1]);
@@ -3108,7 +3217,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//DMR BS Types
if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 )
{
printw ("S[%lld] ", call_matrix[9-j][3]); //%d
// printw ("S[%lld] ", call_matrix[9-j][3]); //%d
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
@@ -3116,14 +3225,31 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//DMR MS Types
if (call_matrix[9-j][0] == 32 || call_matrix[9-j][0] == 33 || call_matrix[9-j][0] == 34 )
{
printw ("S[%lld] ", call_matrix[9-j][3]);
// printw ("S[%lld] ", call_matrix[9-j][3]);
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
}
printw ("%s ", getDateC(call_matrix[9-j][5]) ); //You're welcome
printw ("%s \n", getTimeC(call_matrix[9-j][5]) ); //Remus
// #ifdef LIMAZULUTWEAKS
//Group Name Labels from CSV import
for (int k = 0; k < state->group_tally; k++)
{
if (state->group_array[k].groupNumber == call_matrix[9-j][1])
{
attron(COLOR_PAIR(4));
printw ("[%s]", state->group_array[k].groupName);
printw ("[%s] ", state->group_array[k].groupMode);
}
else if (state->group_array[k].groupNumber == call_matrix[9-j][2])
{
attron(COLOR_PAIR(4));
printw ("[%s]", state->group_array[k].groupName);
printw ("[%s] ", state->group_array[k].groupMode);
}
}
// #endif
printw ("\n");
}
//EDACS and ProVoice, outside of timestamp loop
@@ -3131,12 +3257,28 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{
if (call_matrix[j][3] != 0)
{
printw ("| %s ", SyncTypes[call_matrix[j][0]]);
printw ("| ");
printw ("%s ", getDateC(call_matrix[j][5]) );
printw ("%s ", getTimeC(call_matrix[j][5]) );
printw ("LCN [%2lld] ", call_matrix[j][1]);
printw ("Group [%8lld] ", call_matrix[j][2]);
printw ("Source [%8lld] ", call_matrix[j][3]);
printw ("%s ", getDateC(call_matrix[j][5]) );
printw ("%s \n", getTimeC(call_matrix[j][5]) );
//test
for (int k = 0; k < state->group_tally; k++)
{
if (state->group_array[k].groupNumber == call_matrix[j][2])
{
attron(COLOR_PAIR(4));
printw ("[%s] ", state->group_array[k].groupName);
}
else if (state->group_array[k].groupNumber == call_matrix[j][3])
{
attron(COLOR_PAIR(4));
printw ("[%s] ", state->group_array[k].groupName);
}
}
//end test
printw ("\n");
}
}
@@ -3199,10 +3341,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr)
{
if (state->M == 1) state->M = 0;
if (state->M == 1 || state->M == 0x21) state->M = 0;
else state->M = 1;
}
if (c == 54) // '6' key, toggle force rc4 key over missing pi header/late entry
{
if (state->M == 1 || state->M == 0x21) state->M = 0;
else state->M = 0x21;
}
if (c == 105) //'i' key, toggle signal inversion on inverted types
{
//Set all signal for inversion or uninversion
@@ -3261,8 +3409,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
}
}
@@ -3394,6 +3542,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
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->active_channel, 0, sizeof(state->active_channel));
//reset dmr blocks
dmr_reset_blocks (opts, state);
@@ -3417,8 +3567,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//RIGCTL
if (opts->p25_trunk == 1 && opts->use_rigctl == 1) SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
//rtl_udp
if (opts->p25_trunk == 1 && opts->audio_in_type == 3) rtl_udp_tune (opts, state, state->p25_cc_freq);
//rtl
#ifdef USE_RTLSDR
if (opts->p25_trunk == 1 && opts->audio_in_type == 3) rtl_dev_tune (opts, state->p25_cc_freq);
#endif
state->last_cc_sync_time = time(NULL);
}
@@ -3443,6 +3597,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
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->active_channel, 0, sizeof(state->active_channel));
//reset dmr blocks
dmr_reset_blocks (opts, state);
@@ -3466,8 +3622,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//RIGCTL
if (opts->p25_trunk == 1 && opts->use_rigctl == 1) SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
//rtl_udp
if (opts->p25_trunk == 1 && opts->audio_in_type == 3) rtl_udp_tune (opts, state, state->p25_cc_freq);
//rtl
#ifdef USE_RTLSDR
if (opts->p25_trunk == 1 && opts->audio_in_type == 3) rtl_dev_tune (opts, state->p25_cc_freq);
#endif
state->last_cc_sync_time = time(NULL);
}
@@ -3533,8 +3693,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
state->nxdn_location_sys_code = 0;
sprintf (state->nxdn_location_category, "%s", " ");
state->nxdn_last_ran = 0;
state->nxdn_ran = 0;
state->nxdn_last_ran = -1; //0
state->nxdn_ran = 0; //0
state->nxdn_rcn = 0;
state->nxdn_base_freq = 0;

View File

@@ -2,26 +2,59 @@
#include "dsd.h"
#include "p25p1_heuristics.h"
void
resetState (dsd_state * state)
//fixed the memory leak, but now random segfaults occur -- double free or corruption (out) or (!prev)
void resetState (dsd_state * state)
{
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_p = state->dibit_buf + 200;
// memset (state->dibit_buf, 0, sizeof (int) * 200);
state->repeat = 0; //not sure yet
//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;
//state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
//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;
//state->wav_out_bytes = 0;
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
state->repeat = 0; //repeat frame?
//Audio Buffer -- Free Allocated Memory
free (state->audio_out_buf);
free (state->audio_out_float_buf);
free (state->audio_out_bufR);
free (state->audio_out_float_bufR);
//Audio Buffer -- Memset/Init/Allocate Memory per slot
//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->jitter = -1;
state->synctype = -1;
@@ -31,76 +64,73 @@ resetState (dsd_state * state)
state->umid = 0;
state->minref = -12000;
state->maxref = 12000;
state->lastsample = 0;
for (i = 0; i < 128; i++)
{
state->sbuf[i] = 0;
}
{
state->sbuf[i] = 0;
}
state->sidx = 0;
for (i = 0; i < 1024; i++)
{
state->maxbuf[i] = 15000;
}
{
state->maxbuf[i] = 15000;
}
for (i = 0; i < 1024; i++)
{
state->minbuf[i] = -15000;
}
{
state->minbuf[i] = -15000;
}
state->midx = 0;
state->err_str[0] = 0;
sprintf (state->fsubtype, " ");
sprintf (state->ftype, " ");
state->symbolcnt = 0;
state->rf_mod = 0;
state->numflips = 0;
state->lastsynctype = -1;
state->lastp25type = 0;
state->offset = 0;
state->carrier = 0;
for (i = 0; i < 25; i++)
{
for (j = 0; j < 16; j++)
{
state->tg[i][j] = 48;
}
}
state->tgcount = 0;
state->lasttg = 0;
state->lastsrc = 0;
state->nac = 0;
//Reset Voice Errors in C0 and C1 (or remaining Codewords in IMBE)
state->errs = 0;
state->errs2 = 0;
state->mbe_file_type = -1;
state->errsR = 0;
state->errs2R = 0;
//Misc -- may not be needed
state->optind = 0;
state->numtdulc = 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;
state->debug_audio_errors = 0;
state->debug_header_errors = 0;
state->debug_header_critical_errors = 0;
//unsure if these are still used or ever were used,
// 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->nxdn_last_ran = 0;
// state->payload_algid = 0;
// state->payload_algidR = 0;
state->dmr_encL = 0;
state->dmr_encR = 0;
// //MBE Specific
// //free the memory before allocating it again -- may not use this
// free (state->cur_mp);
// free (state->prev_mp);
// free (state->prev_mp_enhanced);
//each time you run this, it increses memory use by 4MB, massive memory leak
//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
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
// //memory allocation and init on mbe -- may not use this
// 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);
//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,6 +250,7 @@ int UDPBind (char *hostname, int portno)
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)
{
int handle;
@@ -274,8 +275,5 @@ void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency)
address.sin_port = htons(udp_port);
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.
}

View File

@@ -137,6 +137,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
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);
}
opts->rtl_rms = rtl_return_rms();
#endif
}

View File

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

View File

@@ -121,26 +121,23 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
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);
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
if (opts->payload == 1)
{
fprintf (stderr, "\n");
fprintf (stderr, " FACCH Payload ");
fprintf (stderr, " FACCH1 Payload ");
for (int i = 0; i < 12; i++)
{
fprintf (stderr, "[%02X]", m_data[i]);
}
// fprintf (stderr, " - %03X %03X", check, crc);
if (crc != check && opts->payload == 1)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
}
}
@@ -251,16 +248,14 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
state->nxdn_last_ran = ran;
}
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);
fprintf (stderr, "PF 1/1");
if (crc != check)
{
fprintf (stderr, " SACCH NSF");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
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);
//I'm placing this here, my observation is that SACCH NSF
//is almost always, if not always, just IDLE
else fprintf (stderr, " IDLE");
if (opts->payload == 1)
{
@@ -269,7 +264,15 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
{
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
@@ -296,9 +299,10 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
else fprintf (stderr, " ");
fprintf (stderr, "%s", KNRM);
fprintf (stderr, "PF %d/4", part_of_frame+1);
if (crc != check)
{
fprintf (stderr, " SACCH SF%d", sf);
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
@@ -332,16 +336,17 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
NXDN_SACCH_Full_decode (opts, state);
}
if (opts->payload == 1)
{
fprintf (stderr, "\n");
fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
for (int i = 0; i < 4; i++)
{
fprintf (stderr, "[%02X]", m_data[i]);
}
// if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
}
// if (opts->payload == 1)
// {
// fprintf (stderr, "\n");
// fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
// for (int i = 0; i < 4; i++)
// {
// fprintf (stderr, "[%02X]", m_data[i]);
// }
// // if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
// }
}
}
@@ -428,15 +433,10 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
check = check | trellis_buf[i+184];
}
if (crc != check)
{
fprintf (stderr, "%s", KYEL);
if (type == 0) fprintf (stderr, " UDCH");
if (type == 1) fprintf (stderr, " FACCH2");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
fprintf (stderr, "%s", KYEL);
if (type == 0) fprintf (stderr, " UDCH");
if (type == 1) fprintf (stderr, " FACCH2");
fprintf (stderr, "%s", KNRM);
uint8_t f2u_message_buffer[400]; //199
memset (f2u_message_buffer, 0, sizeof(f2u_message_buffer));
@@ -470,6 +470,14 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
if (i == 13) fprintf (stderr, "\n ");
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 (type == 0)
@@ -724,12 +732,6 @@ 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
//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);
else if (opts->aggressive_framesync == 0) NXDN_decode_scch (opts, state, trellis_buf, direction);
@@ -743,7 +745,13 @@ void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint
{
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);
@@ -833,14 +841,11 @@ 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];
}
if (crc[0] != check[0] || crc[1] != check[1])
{
if (type == 0) fprintf (stderr, " UDCH2");
if (type == 1) fprintf (stderr, " FACCH3");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
fprintf (stderr, "%s", KYEL);
if (type == 0) fprintf (stderr, " UDCH2");
if (type == 1) fprintf (stderr, " FACCH3");
fprintf (stderr, "%s", KNRM);
if (crc[0] == check[0] && crc[1] == check[1])
{
@@ -864,8 +869,17 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
if (i == 12) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", f3_udch2_bytes[i]);
}
// fprintf (stderr, " - %03X %03X", check[0], crc[0]);
// fprintf (stderr, " - %03X %03X", check[1], crc[1]);
if ( (crc[0] != check[0] || crc[1] != check[1]) && opts->payload == 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)
{

View File

@@ -15,10 +15,13 @@
void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
{
uint8_t SACCH[400]; //72
uint8_t sacch_bytes[10];
uint32_t i;
uint8_t CrcCorrect = 1;
memset (SACCH, 0, sizeof (SACCH));
memset (sacch_bytes, 0, sizeof (sacch_bytes));
/* Consider all SACCH CRC parts as correct */
CrcCorrect = 1;
@@ -41,6 +44,17 @@ 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_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() */
@@ -60,6 +74,8 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
MessageType |= (ElementsContent[6] & 1) << 1;
MessageType |= (ElementsContent[7] & 1) << 0;
nxdn_message_type (opts, state, MessageType);
/* Save the "F1" and "F2" flags */
state->NxdnElementsContent.F1 = ElementsContent[0];
state->NxdnElementsContent.F2 = ElementsContent[1];
@@ -143,16 +159,20 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//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_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
memset(state->active_channel, 0, sizeof(state->active_channel));
opts->p25_is_tuned = 0;
rtl_udp_tune (opts, state, state->p25_cc_freq);
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
state->last_cc_sync_time = time(NULL); //allow tuners a second to catch up, particularly rtl input
}
break;
@@ -173,8 +193,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
}
} /* End switch(MessageType) */
nxdn_message_type (opts, state, MessageType);
} /* End NXDN_Elements_Content_decode() */
//externalize multiple sub-element handlers
@@ -570,9 +588,10 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
}
if (state->M == 1) state->nxdn_cipher_type = 0x1;
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//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_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
@@ -581,7 +600,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
state->last_vc_sync_time = time(NULL);
//
rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
@@ -599,6 +618,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
fprintf (stderr, " Key Loaded: %lld", state->rkey_array[DestinationID]);
}
if (state->M == 1) state->nxdn_cipher_type = 0x1;
#endif
}
}
@@ -791,7 +811,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
//this PDU is constantly pumped out on the CC CAC Message
if (opts->p25_trunk == 1)
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
{
long int ccfreq = 0;
//if using rigctl, we can poll for the current frequency
@@ -801,7 +821,7 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
}
//if using rtl input, we can ask for the current frequency tuned
else if (opts->audio_in_type == 3)
else if (opts->audio_in_type == 3) //after changing to rtl_dev_tune, this may lag a bit due to delay in sample delivery?
{
ccfreq = (long int)opts->rtlsdr_center_freq;
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
@@ -1125,56 +1145,9 @@ 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];
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
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" */
if(CipherType != 0 && MessageType == 0x1)
{
@@ -1384,8 +1357,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)
if (rep1 != 0 && rep1 != 31)
{
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 Ch: %d TGT: %d-%d; ", rep1, rep2, id); //Private TGT
if (gu == 0) sprintf (state->active_channel[rep1], "Active Group 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
state->last_active_time = time(NULL);
}
@@ -1431,7 +1404,8 @@ 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
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block
{
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
//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 && ((time(NULL) - state->last_vc_sync_time) > 1) && freq != 0)
{
//rigctl
if (opts->use_rigctl == 1)
@@ -1452,9 +1426,10 @@ 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->M == 1) state->nxdn_cipher_type = 0x1;
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//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_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
@@ -1462,13 +1437,14 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL); //should we use this here, or not?
//
rtl_udp_tune (opts, state, freq);
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
//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
if (state->rkey_array[id] != 0) state->R = state->rkey_array[id];
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 cac_bits[300];
uint8_t facch2_bits[348]; //facch2 or udch, same amount of bits
uint8_t facch3_bits[288]; //facch3 or udch2, same amoount of bits
uint8_t facch3_bits[288]; //facch3 or udch2, same amount of bits
//nxdn bit buffer, for easy assignment handling
int nxdn_bit_buffer[364];
@@ -252,7 +252,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
if (opts->payload == 1)
fprintf (stderr, "L%02X - ", lich);
}
else if (voice || facch || sacch || facch2 || cac)
else if (voice || facch || sacch || facch2 || udch || cac)
{
if (opts->frame_nxdn48 == 1)
{
@@ -396,6 +396,9 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
#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
if (voice && !facch) //voice only, no facch steal
{
@@ -461,9 +464,18 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
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
// 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 & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
if (facch & 2)
{
if (memcmp (facch_bits_a, facch_bits_b, 144) != 0)
nxdn_deperm_facch(opts, state, facch_bits_b);
}
if (voice)
{
//restore MBE file open here
@@ -488,6 +500,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * 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
}
}

View File

@@ -295,9 +295,20 @@ 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
else if (lc_format == 0x4F) //# Call Termination/Cancellation
{
fprintf (stderr, " Call Termination/Cancellation");
fprintf (stderr, " Call Termination");
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
if (opts->use_rigctl == 1)
{
@@ -316,9 +327,10 @@ 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);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
state->lasttg = 0;
state->lastsrc = 0;
state->payload_algid = 0;
@@ -331,7 +343,8 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
rtl_udp_tune (opts, state, state->p25_cc_freq);
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
}
}

View File

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

View File

@@ -171,6 +171,8 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
// TODO: error correction of 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

View File

@@ -172,6 +172,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
// TODO: error correction of 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
@@ -183,6 +185,9 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
//set vc counter to 0
state->p25vc = 0;
//reset dropbytes -- skip first 11 for next LCW
state->dropL = 267;
if (opts->errorbars == 1)
{
fprintf (stderr, "\n");
@@ -366,15 +371,19 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
if (irrecoverable_errors == 0)
{
fprintf (stderr, "%s", KYEL);
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);
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
state->payload_algid = algidhex;
state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA)
{
fprintf (stderr, " Key: %010llX", state->R);
opts->unmute_encrypted_p25 = 1;
}
fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2);
if (state->payload_algid != 0x80 && state->payload_algid != 0x0) //print on payload == 1
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " ENC");
@@ -390,4 +399,45 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
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,14 +337,24 @@ 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
{
//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)
{
int spacing = state->p25_chan_spac[channelt >> 12];
if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
if (state->p25_chan_tdma[channelt >> 12] == 1)
{
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
}
}
}
//rigctl
if (opts->use_rigctl == 1)
@@ -355,13 +365,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq1);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -421,15 +433,26 @@ 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
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)
// 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)
{
int spacing = state->p25_chan_spac[channelt >> 12];
if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32
if (state->p25_chan_tdma[channelt >> 12] == 1)
{
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
}
}
}
//rigctl
if (opts->use_rigctl == 1)
@@ -440,13 +463,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq1);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}

View File

@@ -479,9 +479,9 @@ void process_4V (dsd_opts * opts, dsd_state * state)
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
//set to 21 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#endif
@@ -552,6 +552,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
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");
}
@@ -567,6 +568,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
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");
}
@@ -574,7 +576,11 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
}
if (ec == -1 || ec >= 15)
{
//ESS R-S Failure
//ESS R-S Failure -- run LFSR on current MI if applicable
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);
@@ -640,9 +646,9 @@ void process_2V (dsd_opts * opts, dsd_state * state)
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
//set to 21 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#endif
@@ -651,6 +657,13 @@ void process_2V (dsd_opts * opts, dsd_state * 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
@@ -872,16 +885,5 @@ void processP2 (dsd_opts * opts, dsd_state * state)
state->dmr_stereo = 0;
state->p2_is_lcch = 0;
//bugfix for OSS slot preferred pre-emption on dual voices
//in case or marginal signal or bad decoding and both get stuck on 16, indefinitely muting the non-preferred slot
//BUG: This causes an annoying blink blink in ncurses, just FYI -- find a better workaround
#ifdef AERO_BUILD
if (opts->audio_out_type == 5)
{
//set both to blank value
state->dmrburstL = 17;
state->dmrburstR = 17;
}
#endif
fprintf (stderr, "\n");
}

View File

@@ -118,19 +118,8 @@ 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
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
{
// //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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[channel >> 12] == 1)
{
@@ -148,13 +137,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -203,19 +194,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[channel >> 12] == 1)
{
@@ -232,13 +212,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -320,19 +302,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{
@@ -353,14 +324,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
j = 8; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, tunable_freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, tunable_freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
#endif
}
}
}
@@ -431,19 +404,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[channel >> 12] == 1)
{
@@ -461,13 +423,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -524,19 +488,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[channel >> 12] == 1)
{
@@ -554,13 +507,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq);
if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -680,19 +635,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{
@@ -710,14 +654,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, tunable_freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, tunable_freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
#endif
}
}
}
@@ -857,19 +803,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{
@@ -889,15 +824,17 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, tunable_freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, tunable_freq);
//probably best to only set these when really tuning
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
#endif
}
}
}
@@ -979,19 +916,8 @@ 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
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
{
//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[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)
//changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK
if (1 == 1)
{
if (state->p25_chan_tdma[tunable_chan >> 12] == 1)
{
@@ -1011,15 +937,17 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, tunable_freq);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, tunable_freq);
//probably best to only set these when really tuning
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
#endif
}
}
}
@@ -1092,19 +1020,9 @@ 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
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;
// }
// }
//may be this way independent of whether or not this is QPSK (does C4FM run at 6000 sps?)
if (opts->mod_qpsk == 1)
//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)
{
@@ -1122,13 +1040,15 @@ 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
state->last_vc_sync_time = time(NULL);
}
//rtl_udp
//rtl
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, freq1);
#ifdef USE_RTLSDR
rtl_dev_tune (opts, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
#endif
}
}
}
@@ -1623,7 +1543,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];
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);
process_channel_to_freq (opts, state, channelt);
state->p25_cc_freq = process_channel_to_freq (opts, state, channelt);
process_channel_to_freq (opts, state, channelr);
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

View File

@@ -120,6 +120,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
@@ -142,6 +143,7 @@ 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, " KEY ID 0x%04X", state->payload_keyid);
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, " %s", KRED);
// fprintf (stderr, "ENC");
@@ -153,6 +155,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well
state->dmrburstR = 20;
@@ -176,6 +179,7 @@ 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, " KEY ID 0x%04X", state->payload_keyidR);
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, " %s", KRED);
// fprintf (stderr, "ENC");
@@ -194,6 +198,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0;
state->payload_keyid = 0;
@@ -217,6 +222,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0;
state->payload_keyidR = 0;
@@ -270,13 +276,13 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
if (state->currentslot == 1)
{
state->dmrburstL = 21;
state->dmrburstL = 22;
//close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
}
else
{
state->dmrburstR = 21;
state->dmrburstR = 22;
//close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
}
@@ -369,6 +375,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
@@ -391,6 +398,7 @@ 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, " KEY ID 0x%04X", state->payload_keyid);
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, " %s", KRED);
// fprintf (stderr, "ENC");
@@ -402,6 +410,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - ");
@@ -424,6 +433,7 @@ 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, " KEY ID 0x%04X", state->payload_keyidR);
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, " %s", KRED);
// fprintf (stderr, "ENC");
@@ -441,6 +451,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well
state->payload_keyid = 0;
@@ -464,6 +475,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well
state->payload_keyidR = 0;

View File

@@ -31,12 +31,12 @@
#include <rtl-sdr.h>
#include "dsd.h"
//#define DEFAULT_SAMPLE_RATE 48000 //moved to opts->rtl_bandwidth
#define DEFAULT_SAMPLE_RATE 48000
#define DEFAULT_BUF_LENGTH (1 * 16384)
#define MAXIMUM_OVERSAMPLE 16 //16
#define MAXIMUM_OVERSAMPLE 16
#define MAXIMUM_BUF_LENGTH (MAXIMUM_OVERSAMPLE * DEFAULT_BUF_LENGTH)
#define AUTO_GAIN -100
#define BUFFER_DUMP 4096
#define BUFFER_DUMP 4096
#define FREQUENCIES_LIMIT 1000
@@ -46,7 +46,8 @@ static int ACTUAL_BUF_LENGTH;
static int *atan_lut = NULL;
static int atan_lut_size = 131072; /* 512 KB */
static int atan_lut_coef = 8;
//new for UDP
//UDP -- keep for compatibility reasons
#include <netinet/in.h>
#include <arpa/inet.h>
static pthread_t socket_freq;
@@ -57,7 +58,7 @@ int bandwidth_divisor = 48000; //divide bandwidth by this to get multiplier for
short int volume_multiplier;
short int port;
//
struct dongle_state
{
int exit_flag;
@@ -597,7 +598,6 @@ static void *demod_thread_fn(void *arg)
int nearest_gain(rtlsdr_dev_t *dev, int target_gain)
{
//target_gain = 36;
int i, r, err1, err2, count, nearest;
int* gains;
r = rtlsdr_set_tuner_gain_mode(dev, 1);
@@ -628,10 +628,9 @@ int verbose_set_frequency(rtlsdr_dev_t *dev, uint32_t frequency)
int r;
r = rtlsdr_set_center_freq(dev, frequency);
if (r < 0) {
fprintf (stderr, "WARNING: Failed to set center freq.\n");
fprintf (stderr, " (WARNING: Failed to set Center Frequency). \n");
} else {
//fprintf (stderr, "Tuned to %u Hz.\n", frequency);
fprintf (stderr, "Tuned to center frequency %u Hz.\n", frequency);
fprintf (stderr, " (Center Frequency: %u Hz.) \n", frequency);
}
return r;
}
@@ -679,7 +678,6 @@ int verbose_offset_tuning(rtlsdr_dev_t *dev)
int verbose_auto_gain(rtlsdr_dev_t *dev)
{
int r;
r = rtlsdr_set_tuner_gain_mode(dev, 0);
if (r != 0) {
@@ -692,7 +690,6 @@ int verbose_auto_gain(rtlsdr_dev_t *dev)
int verbose_gain_set(rtlsdr_dev_t *dev, int gain)
{
//gain = 36;
int r;
r = rtlsdr_set_tuner_gain_mode(dev, 1);
if (r < 0) {
@@ -710,7 +707,6 @@ int verbose_gain_set(rtlsdr_dev_t *dev, int gain)
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;
if (ppm_error == 0) {
return 0;}
@@ -732,25 +728,23 @@ int verbose_reset_buffer(rtlsdr_dev_t *dev)
return r;
}
//static void optimal_settings(struct fm_state *fm, int freq, int hopping)
static void optimal_settings(int freq, int rate) //
static void optimal_settings(int freq, int rate)
{
// giant ball of hacks
// seems unable to do a single pass, 2:1
//int r, capture_freq, capture_rate;
int capture_freq, capture_rate;
struct dongle_state *d = &dongle;
struct demod_state *dm = &demod;
struct controller_state *cs = &controller;
dm->downsample = (1000000 / dm->rate_in) + 1;
dm->downsample = (1000000 / dm->rate_in) + 1; //dm->rate_in is the rtl_bandwidth value
if (dm->downsample_passes) {
dm->downsample_passes = (int)log2(dm->downsample) + 1;
dm->downsample = 1 << dm->downsample_passes;
}
capture_freq = freq;
capture_rate = dm->downsample * dm->rate_in;
capture_rate = dm->downsample * dm->rate_in; //
if (!d->offset_tuning) {
capture_freq = freq + capture_rate/4;}
capture_freq = freq + capture_rate/4;} //
capture_freq += cs->edge * dm->rate_in / 2;
dm->output_scale = (1<<15) / (128 * dm->downsample);
if (dm->output_scale < 1) {
@@ -759,6 +753,7 @@ static void optimal_settings(int freq, int rate) //
dm->output_scale = 1;}
d->freq = (uint32_t)capture_freq;
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)
@@ -790,7 +785,6 @@ static void *controller_thread_fn(void *arg)
/* Set the sample rate */
verbose_set_sample_rate(dongle.dev, dongle.rate);
fprintf (stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample);
fprintf (stderr, "Press CTRL + C to close.\n");
while (!exitflag) {
safe_cond_wait(&s->hop, &s->hop_m);
@@ -807,20 +801,16 @@ static void *controller_thread_fn(void *arg)
void dongle_init(struct dongle_state *s)
{
//s->rate = DEFAULT_SAMPLE_RATE;
s->rate = rtl_bandwidth;
s->gain = AUTO_GAIN; // tenths of a dB
s->mute = 0;
s->direct_sampling = 0;
s->offset_tuning = 0; //
s->offset_tuning = 0; //E4000 tuners only
s->demod_target = &demod;
}
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_out = rtl_bandwidth;
s->squelch_level = 0;
@@ -830,16 +820,16 @@ void demod_init(struct demod_state *s)
s->downsample_passes = 0;
s->comp_fir_size = 0;
s->prev_index = 0;
s->post_downsample = 1; // once this works, default = 4
s->post_downsample = 1; //1 -- once this works, default = 4 -- doesn't work on the official rtl-sdr source code either
s->custom_atan = 0;
s->deemph = 0;
s->rate_out2 = -1; // flag for disabled
s->rate_out2 = rtl_bandwidth; // -1 flag for disabled -- this enables low_pass_real, seems to work okay
s->mode_demod = &fm_demod;
s->pre_j = s->pre_r = s->now_r = s->now_j = 0;
s->prev_lpr_index = 0;
s->deemph_a = 0;
s->now_lpr = 0;
s->dc_block = 0;
s->dc_block = 1; //enabling by default, but offset tuning is also enabled, so center spike shouldn't be an issue
s->dc_avg = 0;
pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL);
@@ -856,7 +846,6 @@ void demod_cleanup(struct demod_state *s)
void output_init(struct output_state *s)
{
//s->rate = DEFAULT_SAMPLE_RATE;
s->rate = rtl_bandwidth;
pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL);
@@ -904,7 +893,8 @@ void sanity_checks(void)
}
}
//UDP remote all below HERE
//UDP remote stuff
static unsigned int chars_to_int(unsigned char* buf) {
int i;
@@ -918,9 +908,7 @@ static unsigned int chars_to_int(unsigned char* buf) {
}
static void *socket_thread_fn(void *arg) {
//struct fm_state *fm = arg;
struct demod_state *d = static_cast<demod_state*>(arg);
//int port = 6020;
int r, n;
int sockfd, newsockfd, portno;
socklen_t clilen;
@@ -952,114 +940,34 @@ static void *socket_thread_fn(void *arg) {
while((n = read(sockfd,buffer,5)) != 0) {
if(buffer[0] == 0) {
new_freq = chars_to_int(buffer);
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
dongle.freq = new_freq;
optimal_settings(new_freq, demod.rate_in);
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);
}
/*
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);
return 0;
}
//UDP Control all above HERE
//UDP stuff end
void rtlsdr_sighandler()
{
//fprintf (stderr, "Signal caught, exiting!\n");
//fprintf (stderr, "Press CTRL + C again to close. Thanks. \n"); //Kindly remind user to double tap CTRL + C
fprintf (stderr, "Signal caught, exiting!\n");
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)
{
struct sigaction sigact;
int r;
rtl_bandwidth = opts->rtl_bandwidth * 1000; //multiple by 1000 to get rate
//rtl_bandwidth = 48000;
rtl_bandwidth = opts->rtl_bandwidth * 1000; //reverted back to straight value
bandwidth_multiplier = (bandwidth_divisor / rtl_bandwidth);
//bandwidth_multiplier = 1;
//this needs to be initted first, then we set the parameters
dongle_init(&dongle);
demod_init(&demod);
output_init(&output);
@@ -1070,29 +978,23 @@ void open_rtlsdr_stream(dsd_opts *opts)
controller.freq_len++;
}
if (opts->rtlsdr_ppm_error > 0 || opts->rtlsdr_ppm_error < 0) { //this way will adjust PPM based on negative values as well
if (opts->rtlsdr_ppm_error != 0) {
dongle.ppm_error = opts->rtlsdr_ppm_error;
fprintf (stderr, "Setting RTL PPM Error Set to %d\n", opts->rtlsdr_ppm_error);
}
if (opts->audio_in_type == 3) {
dongle.dev_index = opts->rtl_dev_index;
//rtl_bandwidth = opts->rtl_bandwidth * 1000; //multiple by 1000 to get rate
//rtl_bandwidth = 48000;
//bandwidth_multiplier = rtl_bandwidth / bandwidth_divisor; //find multiple with no remainder if oddball number entered
//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;
}
dongle.dev_index = opts->rtl_dev_index;
// demod.squelch_level = opts->rtl_squelch_level; //no longer used here, used in framesync vc rms value under select conditions
fprintf (stderr, "Setting RTL Bandwidth to %d Hz\n", rtl_bandwidth);
// fprintf (stderr, "Setting RTL Sample Multiplier to %d\n", bandwidth_multiplier);
fprintf (stderr, "Setting RTL RMS Squelch Level to %d\n", opts->rtl_squelch_level);
if (opts->rtl_udp_port != 0) port = opts->rtl_udp_port; //set this here, only open socket thread if set
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 really works
dongle.gain = opts->rtl_gain_value * 10; //multiple by ten to make it consitent with the way rtl_fm works
}
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 */
demod.rate_in *= demod.post_downsample;
@@ -1103,24 +1005,16 @@ void open_rtlsdr_stream(dsd_opts *opts)
if (controller.freq_len > 1) demod.terminate_on_squelch = 0;
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)
{
fprintf (stderr, "Failed to open rtlsdr device %d.\n", dongle.dev_index);
exit(1);
} else {
fprintf (stderr, "Using RTLSDR Device Index: %d. \n", dongle.dev_index); //Kindly tell us which device we are using
fprintf (stderr, "Using RTLSDR Device Index: %d. \n", dongle.dev_index);
}
// 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) {
demod.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(demod.rate_out * 75e-6)))));
}
@@ -1128,9 +1022,11 @@ void open_rtlsdr_stream(dsd_opts *opts)
/* Set the tuner gain */
if (dongle.gain == AUTO_GAIN) {
verbose_auto_gain(dongle.dev);
fprintf (stderr, "Setting RTL Autogain. \n");
} else {
dongle.gain = nearest_gain(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);
@@ -1142,7 +1038,8 @@ void open_rtlsdr_stream(dsd_opts *opts)
usleep(100000);
pthread_create(&demod.thread, NULL, demod_thread_fn, (void*)(&demod));
pthread_create(&dongle.thread, NULL, dongle_thread_fn, (void*)(&dongle));
pthread_create(&socket_freq, NULL, socket_thread_fn, (void *)(&controller));
//only create socket thread IF user specified (for legacy uses), else don't use it
if (port != 0) pthread_create(&socket_freq, NULL, socket_thread_fn, (void *)(&controller));
}
void cleanup_rtlsdr_stream()
@@ -1155,8 +1052,6 @@ void cleanup_rtlsdr_stream()
safe_cond_signal(&output.ready, &output.ready_m);
safe_cond_signal(&controller.hop, &controller.hop_m);
pthread_join(controller.thread, NULL);
//add socket thread
//pthread_join(socket_freq, NULL);
//dongle_cleanup(&dongle);
demod_cleanup(&demod);
@@ -1164,32 +1059,69 @@ void cleanup_rtlsdr_stream()
controller_cleanup(&controller);
rtlsdr_close(dongle.dev);
}
//void get_rtlsdr_sample(int16_t *sample)
//original for safe keeping
// 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)
{
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);
//goto END;
}
pthread_rwlock_wrlock(&output.rw);
//*sample = output.queue.front();
*sample = output.queue.front() * volume_multiplier; //try multiplying by numbers here for 'gain'
*sample = output.queue.front() * volume_multiplier;
output.queue.pop();
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
}

BIN
tone24.wav Normal file

Binary file not shown.

BIN
tone48.wav Normal file

Binary file not shown.

BIN
tone8.wav Normal file

Binary file not shown.

4
virtualsink.sh Normal file
View File

@@ -0,0 +1,4 @@
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_sink2 sink_properties=device.description=Virtual_Sink2