79 Commits

Author SHA1 Message Date
lwvmobile
5c42c50a40 Version Naming Update; 2023-04-25 17:18:35 -04:00
lwvmobile
36399386c5 More NXDN/IDAS Tweaks and Fixes; #115 and #118 2023-04-25 16:00:16 -04:00
lwvmobile
8eee4cd699 NXDN Type-D Decoding/Trunking; NXDN Tweaks; #115 2023-04-23 19:52:36 -04:00
lwvmobile
1410e8bd81 Cap Plus Expansion; Minor DMR Tweaks; #116 2023-04-23 19:50:06 -04:00
lwvmobile
915375fb1c Initial NXDN Type D - 'IDAS' Support; #115 2023-04-13 18:20:58 -04:00
lwvmobile
52fff28dc4 NXDN Array Expansion and Message Tweaks; #113 2023-04-13 11:00:37 -04:00
lwvmobile
bd035622b8 No Color Cmake Build Option #114 2023-04-13 11:00:00 -04:00
lwvmobile
44163710f9 More XPT Work; #110 2023-04-12 18:12:10 -04:00
lwvmobile
44b1ccdeae Hashed DMR TG Multi Key Loading Fix; #112 2023-04-12 13:10:13 -04:00
lwvmobile
34113cb782 housekeeping; 2023-04-09 14:30:05 -04:00
lwvmobile
2a336a9275 Hytera XPT WIP #110 2023-04-08 19:15:33 -04:00
lwvmobile
5c08a9193c Yet Another Cmake Warning Fix #107 2023-03-28 23:33:20 -04:00
lwvmobile
2cae7f9c18 NXDN -- DFA Base Freq Fix; ADJ_SITE_INFO; #106 2023-03-28 17:30:02 -04:00
lwvmobile
e056c97d9d Issue #105 - Make Work with Named Pipe (FIFO) 2023-03-22 20:07:02 -04:00
lwvmobile
dc49e0d08b NXDN DFA Support; 2023-03-22 20:00:41 -04:00
lwvmobile
b639f6af28 Fix Cmake Warnings; 2023-03-21 22:42:09 -04:00
lwvmobile
6b45c4ba9b Issue #105 Segfault Bugfix; 2023-03-21 21:09:45 -04:00
lwvmobile
2062502a59 P2 - TDMA-CC Tuning Bugfix and callstring tweak; 2023-03-21 20:58:44 -04:00
lwvmobile
a490d9ead2 Merge pull request #104 from lwvmobile/lite
NXDN48/96 Tweak;
2023-03-12 15:55:12 -04:00
lwvmobile
c73832ac2c NXDN48/96 Tweak; 2023-03-12 15:42:49 -04:00
lwvmobile
fe1fa79f70 More XPT Tweaks and Notes; 2023-03-09 19:12:57 -05:00
lwvmobile
f2f29f2287 Line Space OCD; 2023-03-09 18:40:36 -05:00
lwvmobile
3181e58b19 Lite to Aero Rebrand; 2023-03-08 02:25:51 -05:00
lwvmobile
6204aec2a5 P25 P1 LCW re-write and updates; 2023-03-08 02:25:29 -05:00
lwvmobile
267180ed0e NCurses LO Return to CC; 2023-03-08 02:04:56 -05:00
lwvmobile
8d9cbb3720 XPT Trunking Tweak; 2023-03-08 02:04:09 -05:00
lwvmobile
8af6d2e185 P25 P1 QPSK MSIZE/SSIZE Tweak; 2023-03-08 02:03:01 -05:00
lwvmobile
abeb92ff8a Fix trunk_hangtime lf to f; Ncurses Fixes; 2023-03-06 03:07:27 -05:00
lwvmobile
be47075611 Fix Fast Scanner and NCurses Display (again) 2023-03-05 05:54:23 -05:00
lwvmobile
1640b58ae4 Fix unintended bug in iden_up_vu; 2023-03-04 20:54:52 -05:00
lwvmobile
7a34d531b1 Literature Update 2023-03-04 19:28:58 -05:00
lwvmobile
0af814c72f P25 TSBK PDU Fix; vPDU PDU Fixes; Scanner Freq Fix 2023-03-04 19:26:44 -05:00
lwvmobile
1477190dea Fast Scan Ncurses Tweak; Update Literature; 2023-03-03 15:38:39 -05:00
lwvmobile
b0cd1881bb P25 - P1 MBF Format Addition; TSBK/vPDU Tweaks; 2023-03-03 15:15:42 -05:00
lwvmobile
44ad75ec17 NXDN Trunking Tweaks and Misc Tweaks; 2023-03-02 22:13:49 -05:00
lwvmobile
1ce487dc13 Trunking -- Faster CC Hunt; 2023-03-01 18:32:29 -05:00
lwvmobile
ed9a96fdc8 Experimental -- Fast Scanner Feature; 2023-03-01 17:56:10 -05:00
lwvmobile
c677efda49 P25 - Remove Test Code; NXDN - Remove Freq Calc; 2023-03-01 17:49:52 -05:00
lwvmobile
fea4f97b89 DMR - XPT Tweaks; Data Header Tweaks; 2023-02-25 16:08:55 -05:00
lwvmobile
f2e3834e0a FID 0x10 - FLCO 0x14, 0x15, 0x16, 0x17, 0x18; 2023-02-24 20:51:47 -05:00
lwvmobile
b8b62ef69a Disable remaining setmod_bw as safety precaution; 2023-02-24 20:46:33 -05:00
lwvmobile
4a8a4a088a NXDN Trunking Tweak - Snap Back to CC on Disc; 2023-02-24 18:41:02 -05:00
lwvmobile
9308c5b251 Fix P_Protect CSBK GI indicator; 2023-02-24 18:39:56 -05:00
lwvmobile
cdfe9435d3 Fix NCurses **tera key display when loaded; 2023-02-24 18:39:01 -05:00
lwvmobile
f6cd915f4d Misc Tweaks; Multi BP; More CapMax FLCO; XPT; 2023-02-23 21:59:08 -05:00
lwvmobile
1dfd59801e Literature Update; 2023-02-22 20:00:24 -05:00
lwvmobile
c4513fab7a NXDN Tweaks and SACCH/FACCH CRC Fixes; 2023-02-22 19:46:06 -05:00
lwvmobile
a3b8839897 Minor Cap+ and XPT Fix; 2023-02-21 13:55:15 -05:00
lwvmobile
9e009867ff Disable/Tweak some setmod_bw defaults; 2023-02-20 17:59:53 -05:00
lwvmobile
e95e2218d9 Cap+ NL; Hytera XPT Trunk Support (experimental) 2023-02-20 12:47:30 -05:00
lwvmobile
a9742043b8 General DMR Tweaks; 64-bit IV from 32-bit MI; 2023-02-20 12:43:16 -05:00
lwvmobile
05eef039c9 DMR - LRRP tweaks; Add LOCN PDU. 2023-02-20 12:41:20 -05:00
lwvmobile
818e952b7b DMR - dheader rewrite; UDT/USBD fix; block tweaks; 2023-02-20 12:40:42 -05:00
lwvmobile
38b962aacf P25 Dibit, Block and PDU Payload Tweaks; 2023-02-20 12:35:44 -05:00
lwvmobile
0217202801 DMR - Fix Cap+ CSBK; Various Minor Fixes; 2023-02-05 16:47:58 -05:00
lwvmobile
ef07b48540 DMR Minor Code Fixes; 2023-02-04 20:10:38 -05:00
lwvmobile
db67a8b227 NCurses Compiler Warning and Call Alert Fix; 2023-02-04 04:35:06 -05:00
lwvmobile
4e2c4577d5 DMR Cap+ CSBK Improvements; 2023-02-03 22:15:13 -05:00
lwvmobile
e581c96560 DMR FLCO Tweaks; P25 Site/RFSS Display; 2023-02-02 20:03:52 -05:00
lwvmobile
f3505269d0 DMR Conf Data CRC9; Message CRC32; Tweaks; 2023-02-01 05:35:21 -05:00
lwvmobile
20ccdbbced DMR FLC Tweaks; CSBK Cleaning; 2023-02-01 05:31:40 -05:00
lwvmobile
fc2fb99502 P25P2 OSS Bugfix; 2023-01-29 18:41:03 -05:00
lwvmobile
143c560958 DMR FLCO - Check PF First; 2023-01-29 16:09:47 -05:00
lwvmobile
d122d7e935 DMR Unknown FLCO Tweaks; PI Tweaks; 2023-01-28 21:00:13 -05:00
lwvmobile
d0f9bb4bad Fix DMR FEC/CRC/RAS Implementation Issues; 2023-01-21 05:43:42 -05:00
lwvmobile
ac752029bd Tweak RAS/CRC; Other Misc Tweaks; 2023-01-19 09:42:42 -05:00
lwvmobile
5b994f5129 NXDN Multi-Key CSV Import; Example Updt; 2023-01-18 12:18:56 -05:00
lwvmobile
ec7d7c24a5 DMR SB/RC Additions; Cap+ LC/CSBK; RAS; 2023-01-17 23:58:52 -05:00
lwvmobile
1d49481f2d Fix/Restore MBEout Files; 'DSP' CACH; Tweaks; 2023-01-17 02:25:53 -05:00
lwvmobile
7ca8cb421c Cap+ FLC/CSBK Tweaks; 2023-01-17 02:08:25 -05:00
lwvmobile
4eb44b3c67 'DSP' File Output for OKDMR - Initial Commit; 2023-01-15 22:04:04 -05:00
lwvmobile
e16e4b61fc Cap+ Things; 2023-01-15 21:22:28 -05:00
lwvmobile
fbd04fa869 Allow Standard BP Key on MBE File Playback; 2023-01-15 18:13:48 -05:00
lwvmobile
7f9b852f36 Fix Audio Gain/Device Out on MBE File Playback; 2023-01-15 18:12:15 -05:00
lwvmobile
f5a7ab2b77 P25 P2 ISCH Var Fix; 2023-01-15 18:09:47 -05:00
lwvmobile
ffe6098fb8 DMR Cap+ Rest Channel FLCO/SLCO Fix; 2023-01-09 19:39:05 -05:00
lwvmobile
157ca8c043 RTL Input Tuning Fix (UDP); Minor Tweaks; 2023-01-09 14:13:00 -05:00
lwvmobile
b722e43a3a dPMR Scrambler Key Support; 2023-01-07 18:41:44 -05:00
lwvmobile
2ba9953d33 'Lite' Optimizations and Tweaks for Win32CYG Build 2023-01-05 18:38:12 -05:00
54 changed files with 1295 additions and 2318 deletions

1
.gitignore vendored
View File

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

View File

@@ -1,9 +1,11 @@
#Ubuntu 18.04 uses 3.10.2 currently -- almost EOL
#Ubuntu 20.04 uses 3.16.3
#Ubuntu 22.04 uses 3.22.1
#Arch currently on 3.26.3
#Arch currently on 3.26.1 -- new nag warning starts on this one, see below
#cmake_minimum_required() should be called prior to this top-level project()
#Cygwin currently using 3.23.2 (or newer)
cmake_minimum_required(VERSION 3.10.2)
project(dsd-fme)
project(dsd-fme-aero)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
#Set curses to ncurses, and wide true for ascii
@@ -17,27 +19,6 @@ if (COLORS)
add_definitions(-DPRETTY_COLORS)
endif ()
#use cmake option -DPVC=ON to enable Provoice Conventional Frame Sync
option(PVC
"Build with Provoice Conventional Frame Sync Enabled" OFF)
if (PVC)
add_definitions(-DPVCONVENTIONAL)
endif ()
#use cmake option -DNXDN=ON to enable new NXDN Sync Pattern Testing
option(NXDN
"Build with new NXDN Sync Pattern Testing Enabled" OFF)
if (NXDN)
add_definitions(-DNXDNTESTSYNC)
endif ()
#use cmake option -DLZ=ON to enable LimaZulu Requested NXDN Tweaks
option(LZ
"Build with new LimaZulu Requested NXDN Tweaks Enabled" OFF)
if (LZ)
add_definitions(-DLIMAZULUTWEAKS)
endif ()
include(git_revision)
git_describe(GIT_TAG)
@@ -70,24 +51,24 @@ list(APPEND SRCS "${CMAKE_CURRENT_BINARY_DIR}/git_ver.c")
include_directories("${PROJECT_SOURCE_DIR}/include")
ADD_EXECUTABLE(dsd-fme ${SRCS} ${HEADERS})
TARGET_LINK_LIBRARIES(dsd-fme ${LIBS})
ADD_EXECUTABLE(dsd-fme-aero ${SRCS} ${HEADERS})
TARGET_LINK_LIBRARIES(dsd-fme-aero ${LIBS})
include(GNUInstallDirs)
install(TARGETS dsd-fme DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS dsd-fme-aero DESTINATION ${CMAKE_INSTALL_BINDIR})
# man page
find_program(HELP2MAN_FOUND help2man)
if (HELP2MAN_FOUND)
add_custom_command(TARGET dsd-fme POST_BUILD
add_custom_command(TARGET dsd-fme-aero POST_BUILD
COMMAND help2man
ARGS -n "Digital Speech Decoder"
--version-string=${GIT_TAG}
-o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1
-o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-aero.1
--no-info
$<TARGET_FILE:dsd-fme>
$<TARGET_FILE:dsd-fme-aero>
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-aero.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif()
# uninstall target

View File

@@ -1,18 +1,6 @@
## Notice
# 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").
This branch is for modifications to make a Windows 32-bit binary to be precompiled, please DO NOT use this branch if you are a Linux User, or copy any contents out of here to modify your existing setup!
## License
Copyright (C) 2010 DSD Author

View File

@@ -1,23 +0,0 @@
#! /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

View File

@@ -1,67 +0,0 @@
#! /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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -1,181 +0,0 @@
### 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 (1 and 2) . To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed.
```
-ft XDMA decoder class (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 (will need to specify wacn/sys/nac manually)
-fx X2-TDMA
```
## New -- Experimental Conventional Frequency "Fast Scanner"
This feature is used to allow DSD-FME to use RIGCTL or RTL input and cycle through frequencies as fast as possible to attain a frame sync.
This 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 NXDN98 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 is purely set by your CPU/GPU, and also by other factors like using SDR++ server to connect to a SDR++ client, or RTL_TCP server to client, etc, so faster computers scan faster, and slower will scan slower, slower scans may require multiple duplicate entries into your scanner csv file if you make a really large one.
Please Note: DMR Simplex may not behave well on fast scan, I have not been able to test it as such, but given the nature of the on-off timeslot signalling on DMR Simplex, missed frame syncs and skipping/resuming scan may occur.
## 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
`dsd-fme -ft -i rtl:0:154.9875M:26:-2:8:0:6020 `
```
RTL-SDR options:
WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>
Usage: rtl:dev:freq:gain:ppm:bw:sq:udp
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 = 26)(0 = Hardware AGC, not recommended)
ppm <num> RTL-SDR PPM Error (default = 0)
bw <num> RTL-SDR VFO Bandwidth kHz (default = 12)(6, 8, 12, 24)
sq <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)
udp <num> RTL-SDR UDP Remote Port (default = 6020)
Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:12: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 (CQPSK) with P1 Control Channel (Should switch symbol rate and center on Phase 2 audio channels)
`dsd-fme -i tcp -T -U 4532 -N -mq 2> log.ans`
--P25 Trunking Phase 2 TDMA Control Channel systems with CQPSK (non Phase 1 systems)
`dsd-fme -i tcp -T -U 4532 -N -f2 -m2 2> log.ans`
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: CQPSK Phase 1 and Phase 2 Systems are subceptible to LSM distortion issues, but seem to do okay, but require really good signal. Some CRC issues still occur with Phase 2 TDMA LCCH Mac Signal that can affect reliability, I believe this issue is ultimately caused by the PSK demodulation inside of FME. I also don't believe this will work on 8-level PSK, but I cannot determine that at the moment. Update: I have improved the LCCH Mac Signal decoding my increasing the QPSK decision point buffers to their maximum values.
Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have been carried out. Cap+, Con+, and TIII systems seem to do well with trunking now. Placing the frequency for the control channel at channel map 0 in your channel_map.csv file is not required now if using RIGCTL or the RTL Input, both can poll the VFO for the current frequency if it believes its on a control channel, but setting a fake channel number (i.e. 999) first with the CC frequency will result in finding the CC faster on startup if desired. If you need to map out your channels for TIII, you can observe the console output and look for channel numbers. For conveniece I have included the DSDPlus channel numbering (as best as I can figure it, but they seem consistent) into the console print so it will make it easier for users from DSDPlus to map frequencies into the channel_map.csv file. Make sure your channel numbers are the Cd (channel decimal) values from the log, and not the C+ (dsdplus) values. Notice: TIII Site ID value needs work to determine proper DMRLA values for system area and sub area.
```
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, Rest Channels 1 and 2 will share the same frequency, 3 and 4 will share, 5 and 6 will share, and 7-8 will share, as Capacity Plus counts each 'channel' as two seperate channels (LSN), one for each time slot. Capacity Plus Quirk: DSD-FME makes its best effort to follow the rest channel in the event that the sync is lost for longer than the hangtime, but occassionally, DSD-FME will lose the rest channel and will have to hunt through all frequencies to find it again.
Trunking Note4: NXDN Trunking v1 will require a channel map. Please see the example folder for an appropriate channel map. NOTICE: NXDN trunking will not work properly with RTL input method due to the internal handling of the RTL dongle, when using squelch, it will effectively stop all processing (including trunking/tuning) until signal is regained, but squelch is required on NXDN to prevent false sync patterns.
NXDN Trunking Update: NXDN DFA (Direct Frequency Assignment) has been coded from the v2 documents, so using a channel map may not be required, as long as the DFA is configured with standard values, and not 'system definable' values. This will only work on trunking systems that use DFA (newer systems) in accordance to the v2 CAI document NXDN TS 1-A Version 2.0 September 2016. If the system uses 'system definable' values, then make sure to put the channels in a channel map csv file as as the 16-bit OFN values for proper tuning.
NXDN 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: Experimental Code has been added for XPT system slco/flco/csbk decoding and trunking. The setup will be similar to Capacity Plus trunking in the csv file, listing each LSN channel to a frequency (see examples/hytera_xpt_chan.csv). Currently, this set up is working with smaller XPT systems that I have been able to test with.
## NCurses Keyboard Shortcuts ##
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 dmr privacy key assertion over fid and svc bits
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
p - stop per call decoded wav files
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)
2 - Lockout Tuning/Playback of TG in Slot 2 (Current Session Only)
0 - Toggle Audio Smoothing - May produce crackling if enabled on RTL/TCP or wav/bin files
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)
u - Toggle Trunking Tuning to Private Calls (DMR T3, P25)
d - Toggle Trunking Tuning to Data Calls (DMR T3)
```

View File

@@ -1,127 +0,0 @@
## 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 22.04 and RPi Bullseye 64-bit has been tested working with the installer script and functions appropriately.
If you need all dependencies build and installed first (only on Debian/Ubuntu/Mint/Pi), run:
```
wget https://raw.githubusercontent.com/lwvmobile/dsd-fme/main/download-and-install.sh
chmod +x download-and-install.sh
./download-and-install.sh
```
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
```
### Ubuntu 18.04/LM19/Buster Note:
The above install.sh should now function on older system types. You can elect to manually follow the steps down below. Do NOT Manually build and install ITPP 4.3.1 on older systems, it is currently not wanting to build on Ubuntu 18.04 and Linux Mint 19. Install it from the repository instead.
## Manual Install
First, install dependency packages. This guide will assume you are using Debian/Ubuntu based distros. Check your package manager for equivalent packages if different.
```
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
```
## Headless
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
```
Optional 'Virtual Sinks' for routing audio from SDR++ or GQRX, Media Players, etc. into DSD-FME
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.
```
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

@@ -1,10 +0,0 @@
ChannelNumber(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 ChannelNumber(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

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

View File

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

@@ -1,6 +0,0 @@
ChannelNumber(dec),frequency(Hz) (do not delete this line or won't import properly)
1,851375000
2,851800000
3,855987500
4,858487500
5,852312500
1 ChannelNumber(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

View File

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

@@ -1,10 +0,0 @@
LSN Number(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 Number(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

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

View File

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

View File

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

View File

@@ -1,40 +0,0 @@
#example trunking sh scripts (SDR++ and RTL Input) -T = trunking
#make sure to put a # in front of all lines except the one you wish to use
#P25 P1 FDMA CC with C4FM
#dsd-fme -i tcp -U 4532 -T -N 2> log.ans
#dsd-fme -i rtl:0:850M:26:-2:8:0:6020 -T -N 2> log.ans
#P25 P1 FDMA CC with QPSK (Simulcast)
#dsd-fme -i tcp:192.168.7.8:7355 -U 4532 -T -mq -N 2> log.ans
#dsd-fme -i rtl:0:855.625M:26:-2:12:0:6020 -T -mq -N 2> log.ans
#P25 P2 TDMA CC with QPSK (Simulcast)
#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:26:-2:12:0:6020 -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:26:-2:8:0:6020 -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:26:-2:24:0:6020 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
#NXDN48 Trunking with Channel Map (Custom Channels > 800)
#dsd-fme -fi -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans
#NOTE! NXDN Trunking will not work correctly with the RTL input method
#NXDN96 Trunking with Channel Map (Custom Channels > 800)
#dsd-fme -fn -i tcp -T -U 4532 -C channel_map.csv -N 2> log.ans
#NOTE! NXDN Trunking will not work correctly with the RTL input method
#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
#Having a -G group.csv is purely optional, but useful if you want to block groups, or give groups names

View File

@@ -58,11 +58,14 @@
#include "p25p1_heuristics.h"
//OSS support
#include <sys/soundcard.h>
#include <pulse/simple.h> //PULSE AUDIO
#include <pulse/error.h> //PULSE AUDIO
#define SAMPLE_RATE_IN 48000 //48000
#define SAMPLE_RATE_OUT 8000 //8000,
#define SAMPLE_RATE_OUT 48000 //8000,
#ifdef USE_RTLSDR
#include <rtl-sdr.h>
@@ -201,6 +204,7 @@ typedef struct
int audio_in_type;
char audio_out_dev[1024];
int audio_out_fd;
int audio_out_fdR; //right channel audio for OSS hack
SNDFILE *audio_out_file;
SF_INFO *audio_out_file_info;
@@ -335,12 +339,12 @@ typedef struct
float trunk_hangtime; //hangtime in seconds before tuning back to CC
int scanner_mode; //experimental -- use the channel map as a conventional scanner, quicker tuning, but no CC
//csv import filenames
char group_in_file[1024];
char lcn_in_file[1024];
char chan_in_file[1024];
char key_in_file[1024];
char key_in_file[1024];
//end import filenames
//reverse mute
@@ -365,8 +369,8 @@ typedef struct
//Trunking - Tune Data Calls
uint8_t trunk_tune_data_calls;
//Trunking - Tune Enc Calls (P25 only on applicable grants with svc opts)
uint8_t trunk_tune_enc_calls;
//OSS audio - slot preference
uint8_t slot_preference;
//'DSP' Format Output
uint8_t use_dsp_output;
@@ -548,7 +552,7 @@ typedef struct
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
uint8_t cap_plus_csbk_bits[2][12*8*8]; //CSBK Cap+ FL initial and appended block bit storage, by slot
uint8_t cap_plus_block_num[2]; //received block number storage -- per time slot
uint8_t cap_plus_block_num; //received block number storage
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)
@@ -563,7 +567,6 @@ typedef struct
char dmr_lrrp_gps[2][200]; //2 slots by 99 char string for string lrrp gps
char dmr_site_parms[200]; //string for site/net info depending on type of DMR system (TIII or Con+)
char call_string[2][200]; //string for call information
char active_channel[31][200]; //string for storing and displaying active trunking channels
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
@@ -651,7 +654,6 @@ typedef struct
int lcn_freq_roll; //number we have 'rolled' to in search of the CC
time_t last_cc_sync_time; //use this to start hunting for CC after signal lost
time_t last_vc_sync_time; //flag for voice activity bursts, tune back on con+ after more than x seconds no voice
time_t last_active_time; //time the a 'call grant' was received, used to clear the active_channel strings after x seconds
int is_con_plus; //con_plus flag for knowing its safe to skip payload channel after x seconds of no voice sync
//new nxdn stuff
@@ -668,7 +670,7 @@ typedef struct
char nxdn_location_category[14];
uint32_t nxdn_location_sys_code;
uint16_t nxdn_location_site_code;
//channel access information
uint8_t nxdn_rcn;
uint8_t nxdn_base_freq;
@@ -683,8 +685,8 @@ typedef struct
uint64_t late_entry_mi_fragment[2][7][3];
//dmr manufacturer branding and sub_branding (i.e., Motorola and Con+)
char dmr_branding[99];
char dmr_branding_sub[99];
char dmr_branding[20];
char dmr_branding_sub[80];
//Remus DMR End Call Alert Beep
int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag
@@ -750,26 +752,6 @@ typedef struct
#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311"
#define PROVOICE_EA_SYNC "31131311331331111133131311311133"
//define the provoice conventional string pattern to default 85/85 if not enabled, else mute it so we won't double sync on accident in frame_sync
#ifdef PVCONVENTIONAL
#define PROVOICE_CONV "00000000000000000000000000000000" //all zeroes should be unobtainable string in the frame_sync synctests
#define INV_PROVOICE_CONV "00000000000000000000000000000000" //all zeroes should be unobtainable string in the frame_sync synctests
#else
#define PROVOICE_CONV "13131333111311311313131313131313" //TX 85 RX 85 (default programming value)
#define INV_PROVOICE_CONV "31313111333133133131313131313131" //TX 85 RX 85 (default programming value)
#endif
//we use the short sync instead of the default 85/85 wnen PVCONVENTIONAL is defined by cmake
#define PROVOICE_CONV_SHORT "1313133311131131" //16-bit short pattern, last 16-bits change based on TX an RX values
#define INV_PROVOICE_CONV_SHORT "3131311133313313"
//In this pattern (inverted polarity, the norm for PV) 3 is bit 0, and 1 is bit 1 (2 level GFSK)
//same pattern //TX //RX
// Sync Pattern = 3131311133313313 31331131 31331131 TX/RX 77 -- 31331131 symbol = 01001101 binary = 77 decimal
// Sync Pattern = 3131311133313313 33333333 33333333 TX/RX 0 -- 33333333 symbol = 00000000 binary = 0 decimal
// Sync Pattern = 3131311133313313 33333331 33333331 TX/RX 1 -- 33333331 symbol = 00000001 binary = 1 decimal
// Sync Pattern = 3131311133313313 13131133 13131133 TX/RX 172 -- 13131133 symbol = 10101100 binary = 172 decimal
// Sync Pattern = 3131311133313313 11333111 11333111 TX/RX 199 -- 11333111 symbol = 11000111 binary = 199 decimal
// Sync Pattern = 3131311133313313 31313131 31313131 TX/RX 85 -- 31313131 symbol = 01010101 binary = 85 decimal
#define EDACS_SYNC "313131313131313131313111333133133131313131313131"
#define INV_EDACS_SYNC "131313131313131313131333111311311313131313131313"
@@ -820,7 +802,7 @@ void openMbeOutFile (dsd_opts * opts, dsd_state * state);
void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
void openWavOutFile (dsd_opts * opts, dsd_state * state);
void openWavOutFileL (dsd_opts * opts, dsd_state * state);
void openWavOutFileR (dsd_opts * opts, dsd_state * state);
void openWavOutFileR (dsd_opts * opts, dsd_state * state);
void openWavOutFileRaw (dsd_opts * opts, dsd_state * state);
void openSymbolOutFile (dsd_opts * opts, dsd_state * state);
void closeSymbolOutFile (dsd_opts * opts, dsd_state * state);
@@ -873,7 +855,8 @@ short nxdn_filter(short sample);
short dpmr_filter(short sample);
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr);
uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);
/* Global functions */
uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);
void ncursesOpen (dsd_opts * opts, dsd_state * state);
void ncursesPrinter (dsd_opts * opts, dsd_state * state);
@@ -890,7 +873,7 @@ void nxdn_deperm_facch2_udch (dsd_opts * opts, dsd_state * state, uint8_t bits[3
//type-d 'idas' deinterleaving/depuncturing functions
void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint8_t direction);
void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type);
//end
//end
void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType);
void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]);
@@ -957,7 +940,6 @@ uint8_t ComputeCrc5Bit(uint8_t * DMRData);
uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData);
uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData);
//new simplified dmr functions
void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst);
void dmr_data_sync (dsd_opts * opts, dsd_state * state);

View File

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

View File

@@ -1,16 +0,0 @@
#! /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

@@ -773,7 +773,6 @@ void dmr_reset_blocks (dsd_opts * opts, dsd_state * state)
memset (state->dmr_lrrp_source, 0, sizeof(state->dmr_lrrp_source));
memset (state->dmr_cach_fragment, 1, sizeof (state->dmr_cach_fragment));
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
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

View File

@@ -114,7 +114,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
//disabled for dmr_cach testing
tact_okay = 0;
if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1;
if (tact_okay != 1) goto END; //when going to end for bad tact or emb, consider using getdibit or skipdibit to 'stash' dibits and get better return on next sync pattern? in data particularly
if (tact_okay != 1) goto END;
internalslot = state->currentslot = tact_bits[1];
@@ -189,13 +189,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
syncdata[(2*i)+1] = (1 & dibit); // bit 0
//embedded link control
if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E (F for Single/RC)
if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E
{
state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0
}
if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E (F for Single/RC)
if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E
{
state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0
@@ -263,7 +263,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr,"Sync: +DMR ");
}
else fprintf (stderr,"Sync: -DMR ");
vc1 = 1;
//close MBEout file - slot 1
@@ -333,7 +333,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
else sprintf (polarity, "%s", "-");
fprintf (stderr,"Sync: %sDMR %s| Color Code=%02d | VC%d ", polarity, light, state->dmr_color_code, vc);
if (internalslot == 0 && vc1 == 6)
{
//process embedded link control
@@ -361,9 +361,22 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
memcpy (m2, ambe_fr2, sizeof(m2));
memcpy (m3, ambe_fr3, sizeof(m3));
// if ( opts->audio_in_type == 5 && internalslot == 0 && state->dmrburstR != 16 ) //(OSS shim)
// {
// processMbeFrame (opts, state, NULL, ambe_fr, NULL);
// processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
// processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
// }
// if ( opts->audio_in_type == 5 && internalslot == 1 && state->dmrburstL != 16 ) //(OSS shim)
// {
// processMbeFrame (opts, state, NULL, ambe_fr, NULL);
// processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
// processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
// }
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
cach_err = dmr_cach (opts, state, cachdata);
if (opts->payload == 0) fprintf (stderr, "\n");
@@ -383,7 +396,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
{
state->last_vc_sync_time = time(NULL);
state->last_cc_sync_time = time(NULL);
}
}
//'DSP' output to file
if (opts->use_dsp_output == 1)
@@ -403,13 +416,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (pFile, "%X", dsp_byte);
}
fclose (pFile);
}
}
//reset err checks
cach_err = 1;
tact_okay = 0;
emb_ok = 0;
//reset emb components
cc = 25;
power = 9;
@@ -461,12 +474,12 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM);
fprintf (stderr, "\n");
//run refresh if either slot had an active MI in it.
if (state->payload_algid != 0)
if (state->payload_algid >= 0x21)
{
state->currentslot = 0;
dmr_alg_refresh (opts, state);
}
if (state->payload_algidR != 0)
if (state->payload_algidR >= 0x21)
{
state->currentslot = 1;
dmr_alg_refresh (opts, state);
@@ -507,7 +520,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
11, 12, 2, 13, 14,
15, 3, 16, 4, 17, 18,
19, 5, 20, 21, 22, 6, 23
};
};
//add time to mirror printFrameSync
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
@@ -552,8 +565,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
//decode and correct tact and compare
if ( Hamming_7_4_decode (tact_bits) ) tact_okay = 1;
if (tact_okay != 1) goto END;
if (tact_okay != 1) goto END;
internalslot = state->currentslot = tact_bits[1];
@@ -612,7 +624,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
if ( strcmp (sync, DMR_BS_VOICE_SYNC) != 0)
{
sync_okay = 0;
goto END;
goto END;
}
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
@@ -729,12 +741,12 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM);
fprintf (stderr, "\n");
//run refresh if either slot had an active MI in it.
if (state->payload_algid != 0)
if (state->payload_algid >= 0x21)
{
state->currentslot = 0;
dmr_alg_refresh (opts, state);
}
if (state->payload_algidR != 0)
if (state->payload_algidR >= 0x21)
{
state->currentslot = 1;
dmr_alg_refresh (opts, state);

View File

@@ -45,12 +45,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
if(IrrecoverableErrors == 0 && CRCCorrect == 1)
{
//clear stale Active Channel messages here
if ( ((time(NULL) - state->last_active_time) > 3) && ((time(NULL) - state->last_vc_sync_time) > 3))
{
memset (state->active_channel, 0, sizeof(state->active_channel));
}
//update time to prevent random 'Control Channel Signal Lost' hopping
//in the middle of voice call on current Control Channel (con+ and t3)
state->last_cc_sync_time = time(NULL);
@@ -78,7 +73,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//all of these messages share the same format (thankfully)
if (csbk_o == 48) fprintf (stderr, " Private Voice Channel Grant (PV_GRANT)");
if (csbk_o == 49) fprintf (stderr, " Talkgroup Voice Channel Grant (TV_GRANT)");
if (csbk_o == 50) fprintf (stderr, " Broadcast Voice Channel Grant (BTV_GRANT)"); //listed as private in the appendix (error?)
if (csbk_o == 50) fprintf (stderr, " Private Broadcast Voice Channel Grant (BTV_GRANT)");
if (csbk_o == 51) fprintf (stderr, " Private Data Channel Grant: Single Item (PD_GRANT)");
if (csbk_o == 52) fprintf (stderr, " Talkgroup Data Channel Grant: Single Item (TD_GRANT)");
if (csbk_o == 53) fprintf (stderr, " Duplex Private Voice Channel Grant (PV_GRANT_DX)");
@@ -104,21 +99,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
uint32_t target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
uint32_t source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24);
//move mbc variables out of if statement
uint8_t mbc_lb = 0; //
uint8_t mbc_pf = 0;
uint8_t mbc_csbko = 0;
uint8_t mbc_res = 0;
uint8_t mbc_cc = 0;
uint8_t mbc_cdeftype = 0;
uint8_t mbc_res2 = 0;
unsigned long long int mbc_cdefparms = 0;
uint16_t mbc_lpchannum = 0;
uint16_t mbc_abs_tx_int = 0;
uint16_t mbc_abs_tx_step = 0;
uint16_t mbc_abs_rx_int = 0;
uint16_t mbc_abs_rx_step = 0;
fprintf (stderr, "\n");
//added my best guess as to how dsdplus arrives at a dmr channel value (seems pretty consistent) as C+
fprintf (stderr, " Ch [%03X] Cd [%04d] C+ [%04d] - TS [%d] - Target [%08d] - Source [%08d]", lpchannum, lpchannum, pluschannum, lcn, target, source);
@@ -127,33 +107,36 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
if (lpchannum == 0xFFF) //This is from an MBC, signalling an absolute and not a logical
{
//7.1.1.1.2 Channel Grant Absolute Parameters CG_AP appended MBC PDU
mbc_lb = cs_pdu_bits[96]; //
mbc_pf = cs_pdu_bits[97];
mbc_csbko = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[98], 6);
mbc_res = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[104], 4);
mbc_cc = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[108], 4);
mbc_cdeftype = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[112], 4); //see 7.2.19.7 = 0 for channel parms, 1 through FFFF reserved
mbc_res2 = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[116], 2);
long long int mbc_cdefparms = (unsigned long long int)ConvertBitIntoBytes(&cs_pdu_bits[118], 58); //see 7.2.19.7.1
uint8_t mbc_lb = cs_pdu_bits[96]; //
uint8_t mbc_pf = cs_pdu_bits[97];
uint8_t mbc_csbko = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[98], 6);
uint8_t mbc_res = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[104], 4);
uint8_t mbc_cc = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[108], 4);
uint8_t mbc_cdeftype = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[112], 4); //see 7.2.19.7 = 0 for channel parms, 1 through FFFF reserved
uint8_t mbc_res2 = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[116], 2);
uint64_t mbc_cdefparms = (uint64_t)ConvertBitIntoBytes(&cs_pdu_bits[118], 58); //see 7.2.19.7.1
//this is how you read the 58 parm bits according to the appendix 7.2.19.7.1
if (mbc_cdeftype == 0) //if 0, then absolute channel parms
{
mbc_lpchannum = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[118], 12);
mbc_abs_tx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[130], 10);
mbc_abs_tx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[140], 13);
mbc_abs_rx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[153], 10);
mbc_abs_rx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[163], 13);
uint16_t mbc_lpchannum = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[118], 12);
uint16_t mbc_abs_tx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[130], 10);
uint16_t mbc_abs_tx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[140], 13);
uint16_t mbc_abs_rx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[153], 10);
uint16_t mbc_abs_rx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[163], 13);
//tx_int (Mhz) + (tx_step * 125) = tx_freq
//rx_int (Mhz) + (rx_step * 125) = rx_freq
fprintf (stderr, "\n");
fprintf (stderr, " ABS-CHAN [%03X][%04d] - RX INT [%d][%X] - RX STEP [%d][%X]", mbc_lpchannum, mbc_lpchannum, mbc_abs_rx_int, mbc_abs_rx_int, mbc_abs_rx_step, mbc_abs_rx_step );
//DOULBE CHECK APPENDIX C - C.1.1.2 Fixed Channel Plan for accurate information (found it after figuring out calc, so might be worth double checking)
//The Frequency we want to tune is the RX Frequency
freq = (mbc_abs_rx_int * 1000000 ) + (mbc_abs_rx_step * 125);
//tx_freq = (mbc_abs_tx_int * 1000000 ) + (mbc_abs_tx_step * 125);
}
else fprintf (stderr, "\n MBC Channel Grant - Unknown Parms: %015llX", mbc_cdefparms); //for any reserved values
}
//print frequency from absolute
@@ -166,26 +149,8 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
(stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
}
//add active channel string to display
if (lpchannum != 0 && lpchannum != 0xFFF)
{
if (csbk_o == 49 || csbk_o == 50) sprintf (state->active_channel[lcn], "Active Group Ch: %d TG: %d; ", lpchannum, target);
else if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54) sprintf (state->active_channel[lcn], "Active Data Ch: %d TG: %d; ", lpchannum, target);
else sprintf (state->active_channel[lcn], "Active Private Ch: %d TG: %d; ", lpchannum, target);
}
else if (lpchannum == 0xFFF)
{
if (csbk_o == 49 || csbk_o == 50) sprintf (state->active_channel[lcn], "Active Group Ch: %d TG: %d; ", mbc_lpchannum, target);
else if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54) sprintf (state->active_channel[lcn], "Active Data Ch: %d TG: %d; ", mbc_lpchannum, target);
else sprintf (state->active_channel[lcn], "Active Private Ch: %d TG: %d; ", mbc_lpchannum, target);
}
//update last active channel time
state->last_active_time = time(NULL);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0 && csbk_o == 49) goto SKIPCALL; //TV_GRANT
if (opts->trunk_tune_group_calls == 0 && csbk_o == 50) goto SKIPCALL; //BTV_GRANT
if (csbk_o == 50) csbk_o = 49; //flip to normal group call for group tuning
if (opts->trunk_tune_group_calls == 0 && csbk_o == 49) goto SKIPCALL;
//Allow tuning of data calls if user wishes by flipping the csbk_o to a group voice call
if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54)
@@ -762,7 +727,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
uint8_t bank_one = 0;
uint8_t bank_two = 0;
uint8_t b2_start = 0;
uint8_t block_num = state->cap_plus_block_num[ts];
uint8_t block_num = state->cap_plus_block_num;
uint8_t pdflag = 0;
uint8_t pdflag2 = 0;
uint16_t private_target = 0;
@@ -776,12 +741,11 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
int i, j, k, x;
//tg and channel info for trunking purposes
uint16_t t_tg[24];
char cap_active[20]; //local string to concantenate to active channel stuff
//sanity check
if (block_num > 6)
{
state->cap_plus_block_num[ts] = 6;
state->cap_plus_block_num = 6;
block_num = 6;
}
@@ -796,13 +760,13 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//NOTE: this has been changed to store per slot
memset (state->cap_plus_csbk_bits[ts], 0, sizeof(state->cap_plus_csbk_bits[ts]));
for (i = 0; i < 10*8; i++) state->cap_plus_csbk_bits[ts][i] = cs_pdu_bits[i];
state->cap_plus_block_num[ts] = 0;
state->cap_plus_block_num = 0;
}
else //appended block (fl 0) or final block (fl 1)
{
for (i = 0; i < 7*8; i++) state->cap_plus_csbk_bits[ts][i+80+(7*8*block_num)] = cs_pdu_bits[i+24];
block_num++;
state->cap_plus_block_num[ts]++;
state->cap_plus_block_num++;
}
if (rest_channel != state->dmr_rest_channel)
@@ -865,8 +829,9 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
fprintf (stderr, " LSN %02d:", i+1);
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][56+(k*16)+(group_tally*8)], 16);
fprintf (stderr, " TGT %d;", private_target);
// if (opts->trunk_tune_data_calls == 1) t_tg[i] = private_target; //moved to below section
k++;
if (bank_one == 0) bank_one = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display
if (bank_one == 0) bank_one = 1; //flag on bank one if not already for private call listings
}
}
//save for starting point of the next private call bank
@@ -896,8 +861,9 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
fprintf (stderr, " LSN %02d:", i+1);
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][64+(k*16)+(group_tally*8)+(pd_b2*16)], 16); //64
fprintf (stderr, " TGT %d;", private_target);
// if (opts->trunk_tune_data_calls == 1) t_tg[i+8] = private_target; //moved to below section
k++;
if (bank_two == 0) bank_two = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display
if (bank_two == 0) bank_two = 1; //flag on bank one if not already for private call listings
}
}
}
@@ -907,46 +873,19 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
if (fl == 1 || fl == 3)
{
fprintf (stderr, "\n ");
//additive strings for active channels
memset (state->active_channel, 0, sizeof(state->active_channel));
sprintf (state->active_channel[0], "Cap+ ");
state->last_active_time = time(NULL);
k = 0;
x = 0;
//NOTE: New start and end positions will allow the status print
//to contract and expand as needed to prevent this from
//being a four liner CSBK when there is little or no activity
//start position;
start = 0;
if (bank_one & 0xF0) start = 0;
else if (rest_channel < 5) start = 0;
start = 8;
if (bank_one) start = 0;
else if (rest_channel < 8) start = 0;
else if (bank_one & 0xF) start = 4;
else if (rest_channel > 4 && rest_channel < 9) start = 4;
else if (bank_two & 0xF0) start = 8;
else if (rest_channel > 8 && rest_channel < 13) start = 8;
else if (bank_two & 0xF) start = 12;
else if (rest_channel > 12) start = 12;
//end position;
end = 16;
if (bank_two & 0xF) end = 16;
else if (rest_channel > 12) end = 16;
else if (bank_two & 0xF0) end = 12;
else if (rest_channel > 9 && rest_channel < 13) end = 12;
else if (bank_one & 0xF) end = 8;
else if (rest_channel > 4 && rest_channel < 9) end = 8;
else if (bank_one & 0xF0) end = 4;
else if (rest_channel < 5) end = 4;
//end position;
end = 8;
if (bank_two) end = 16;
else if (rest_channel > 8) end = 16;
//start parsing info and listing active LSNs
for (i = start; i < end; i++)
@@ -954,13 +893,10 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//skip an additional k value per bank
if (i == 8) k++;
if (start < 1 && i == 4)
if (i == 4 || i == 12)
fprintf (stderr, "\n ");
if (start < 5 && i == 8)
fprintf (stderr, "\n ");
if (start < 9 && i == 12)
if (i == 8 && start == 0 && end == 16)
fprintf (stderr, "\n ");
fprintf (stderr, "LSN %02d: ", i+1);
@@ -972,11 +908,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
else fprintf (stderr, "Group; ");
//flag as available for tuning if group calls enabled
if (opts->trunk_tune_group_calls == 1) t_tg[i] = tg;
if (tg != 0) k++;
//add active channel to display string
sprintf (cap_active, "LSN:%d TG:%d; ", i+1, tg);
strcat (state->active_channel[i+1], cap_active);
if (tg != 0) k++;
}
else if (pch[i] == 1) //private or data channels
{
@@ -985,24 +917,21 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
else fprintf (stderr, " P||D; ");
//flag as available for tuning if data calls enabled
if (opts->trunk_tune_data_calls == 1) t_tg[i] = tg; //ch[i] = 1;
if (tg != 0) x++;
//add active channel to display string
//NOTE: Consider only adding this if user toggled or else
//lots of short data bursts blink in and out
if (1 == 1) //opts->trunk_tune_data_calls
{
sprintf (cap_active, "LSN:%d PC:%d; ", i+1, tg);
strcat (state->active_channel[i+1], cap_active);
}
if (tg != 0) x++;
}
else if (i+1 == rest_channel) fprintf (stderr, " Rest; ");
else fprintf (stderr, " Idle; ");
}
//debug ncurses terminal display -- LSNs 1-8
// sprintf (state->dmr_lrrp_gps[0], "CAP LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", 1, t_tg[0], 2, t_tg[1], 3, t_tg[2], 4, t_tg[3]);
// sprintf (state->dmr_lrrp_gps[1], "CAP LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", 5, t_tg[4], 6, t_tg[5], 7, t_tg[6], 8, t_tg[7]);
//debug ncurses terminal display -- LSNs 9-16
// sprintf (state->dmr_lrrp_gps[0], "CAP LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", 9, t_tg[8], 10, t_tg[9], 11, t_tg[10], 12, t_tg[11]);
// sprintf (state->dmr_lrrp_gps[1], "CAP LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", 13, t_tg[12], 14, t_tg[13], 15, t_tg[14], 16, t_tg[15]);
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
@@ -1087,7 +1016,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
fprintf (stderr, "%s", KNRM);
}
memset (state->cap_plus_csbk_bits[ts], 0, sizeof(state->cap_plus_csbk_bits[ts]));
state->cap_plus_block_num[ts] = 0;
state->cap_plus_block_num = 0;
} //if (fl == 1 || fl == 3)
} //opcode == 0x3E
@@ -1133,10 +1062,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf(state->dmr_branding_sub, "Con+ ");
//add active channel string for display
sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", lcn, grpAddr);
state->last_active_time = time(NULL);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCON;
@@ -1256,12 +1181,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
fprintf (stderr, " Hytera XPT Site Status - Free LCN: %d SN: %d", xpt_free, xpt_seq);
//strings for active channels
char xpt_active[20];
if (xpt_seq == 0) sprintf (state->active_channel[0], "XPT "); //add initial if sequence 0
else sprintf (state->active_channel[xpt_seq], "%s", ""); //blank current sequence to re-write to
state->last_active_time = time(NULL);
//Print List of LCN with LSN Activity
for (i = 0; i < 6; i++)
{
@@ -1303,19 +1222,12 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//add values to trunking tg/channel potentials
if (tg != 0) t_tg[i+xpt_bank] = tg;
//concantenate string to active channels for ncurses display
if (tg != 0)
{
if (xpt_ch[i] == 3) sprintf (xpt_active, "LSN:%d TG:%d; ", i+xpt_bank+1, tg);
if (xpt_ch[i] == 2) sprintf (xpt_active, "LSN:%d PC:%d; ", i+xpt_bank+1, tg);
//last two are unknown status but have an associated target value
if (xpt_ch[i] == 1) sprintf (xpt_active, "LSN:%d UK:%d; ", i+xpt_bank+1, tg);
if (xpt_ch[i] == 0) sprintf (xpt_active, "LSN:%d UK:%d; ", i+xpt_bank+1, tg);
strcat (state->active_channel[xpt_seq], xpt_active); //add string to active channel seq
}
}
//debug ncurses terminal display
// sprintf (state->dmr_lrrp_gps[0], "XPT SN %d LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", xpt_seq, xpt_bank+1, t_tg[0], xpt_bank+2, t_tg[1], xpt_bank+3, t_tg[2]);
// sprintf (state->dmr_lrrp_gps[1], "XPT SN %d LSN: %02d TG: %03d; LSN: %02d TG: %03d; LSN: %02d TG: %03d;", xpt_seq, xpt_bank+4, t_tg[3], xpt_bank+5, t_tg[4], xpt_bank+6, t_tg[5]);
//add string for ncurses terminal display
sprintf (state->dmr_site_parms, "Free LCN - %d ", xpt_free);

View File

@@ -75,10 +75,9 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
if ( Hamming_7_4_decode (tact_bits) ) cach_okay = 1;
else
{
cach_okay = -1;
SlotTypeOk = 0;
goto END;
goto END;
}
state->currentslot = tact_bits[1];
@@ -180,7 +179,6 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
dibit = (int)state->dmr_stereo_payload[65];
}
else state->dmr_stereo_payload[65] = dibit;
SlotType[8] = (1 & (dibit >> 1)); // bit 1
SlotType[9] = (1 & dibit); // bit 0
@@ -255,14 +253,14 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
}
/* Check and correct the SlotType (apply Golay(20,8) FEC check) */
// golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors
if( Golay_20_8_decode(SlotType) ) SlotTypeOk = 1;
else
{
SlotTypeOk = -1;
SlotTypeOk = 0;
goto END;
goto END;
}
state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0);
@@ -345,7 +343,6 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
//zero out vc frequencies
state->p25_vc_freq[0] = 0;
state->p25_vc_freq[1] = 0;
memset (state->active_channel, 0, sizeof(state->active_channel));
state->last_cc_sync_time = time(NULL);
state->is_con_plus = 0; //con+ flag off
}

View File

@@ -907,7 +907,6 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
{
fprintf (stderr, "[%02X]", slco_bytes[i]);
}
fprintf (stderr, "\n"); //if its a voice frame, we need the line break
}
fprintf (stderr, "%s", KNRM);

View File

@@ -166,7 +166,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
for(i = 0; i < 24; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
state->dmr_stereo_payload[i+66] = dibit;
@@ -176,7 +176,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
sync[i] = (dibit | 1) + 48;
// load the superframe to do embedded signal processing
if(vc > 1) //grab on vc1 values 2-5 B C D and E (F for Single/RC)
if(vc > 1) //grab on vc1 values 2-5 B C D and E
{
state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1
state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0
@@ -212,6 +212,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
power = EmbeddedSignalling[4];
lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
}
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
@@ -295,7 +296,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
}
if (vc == 6)
{
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);

View File

@@ -116,7 +116,7 @@ void LFSR(dsd_state * state)
void LFSR64(dsd_state * state)
{
{
unsigned long long int lfsr = 0;
uint64_t lfsr = 0;
if (state->currentslot == 0)
{
@@ -128,16 +128,19 @@ void LFSR64(dsd_state * state)
for(cnt=0;cnt<32;cnt++)
{
unsigned long long int bit = ( (lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0) ) & 0x1;
uint64_t bit = ( (lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0) ) & 0x1;
lfsr = (lfsr << 1) | bit;
}
// if (state->currentslot == 0) state->payload_miP = lfsr;
// else state->payload_miN = lfsr;
if (state->currentslot == 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " Slot 1");
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
fprintf (stderr, " MI: 0x%016llX", lfsr);
fprintf (stderr, " MI: 0x%016lX", lfsr);
fprintf (stderr, "%s", KNRM);
state->payload_mi = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification
}
@@ -147,7 +150,7 @@ void LFSR64(dsd_state * state)
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " Slot 2");
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR);
fprintf (stderr, " MI: 0x%016llX", lfsr);
fprintf (stderr, " MI: 0x%016lX", lfsr);
fprintf (stderr, "%s", KNRM);
state->payload_miR = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification
}

View File

@@ -325,15 +325,15 @@ uint8_t ComputeCrc5Bit(uint8_t * DMRData)
return CRC;
} /* End ComputeCrc5Bit() */
uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength)
uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength)
{
uint64_t Output = 0;
uint32_t Output = 0;
uint32_t i;
for(i = 0; i < BitLength; i++)
{
Output <<= 1;
Output |= (uint64_t)(BufferIn[i] & 1);
Output |= (uint32_t)(BufferIn[i] & 1);
}
return Output;

View File

@@ -444,17 +444,18 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
if (state->audio_out_idx > opts->delay)
{
// output synthesized speech to sound card
if(opts->audio_out_type == 2)
{
//go F yourself PA
}
else
if (opts->audio_out_type == 5) //OSS
{
//Test just sending it straight on since I think I've figured out the STDIN and RTL for Stereo
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
//OSS
result = write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2));
state->audio_out_idx = 0;
}
else if (opts->audio_out_type == 0)
{
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL);
state->audio_out_idx = 0;
}
else state->audio_out_idx = 0; //failsafe for audio_out == 0
}
@@ -478,15 +479,18 @@ playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
if (state->audio_out_idxR > opts->delay)
{
// output synthesized speech to sound card
if(opts->audio_out_type == 2)
{
//go F yourself PA
}
else
if (opts->audio_out_type == 5) //OSS
{
pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works.
//OSS
result = write (opts->audio_out_fdR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2));
state->audio_out_idxR = 0;
}
else if (opts->audio_out_type == 0)
{
pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL);
state->audio_out_idxR = 0;
}
else state->audio_out_idxR = 0; //failsafe for audio_out == 0
}
@@ -543,7 +547,7 @@ openAudioInDevice (dsd_opts * opts)
//if no extension set, give default of .wav -- bugfix for github issue #105
// if (extension == NULL) extension = ".wav";
// get info of device/file
if (strncmp(opts->audio_in_dev, "-", 1) == 0)
{
@@ -561,6 +565,7 @@ openAudioInDevice (dsd_opts * opts)
exit(1);
}
}
else if (strncmp(opts->audio_in_dev, "tcp", 3) == 0)
{
opts->audio_in_type = 8;
@@ -570,13 +575,13 @@ openAudioInDevice (dsd_opts * opts)
opts->audio_in_file_info->seekable=0;
opts->audio_in_file_info->format=SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE;
opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
if(opts->tcp_file_in == NULL)
{
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
exit(1);
}
}
else if (strncmp(opts->audio_in_dev, "udp", 3) == 0)
{
opts->audio_in_type = 6;
@@ -601,6 +606,10 @@ openAudioInDevice (dsd_opts * opts)
{
opts->audio_in_type = 0;
}
else if((strncmp(opts->audio_in_dev, "/dev/dsp", 8) == 0))
{
opts->audio_in_type = 5;
}
//if no extension set, treat as named pipe or extensionless wav file -- bugfix for github issue #105
else if (extension == NULL)
@@ -667,9 +676,11 @@ openAudioInDevice (dsd_opts * opts)
}
//open pulse audio if no bin or wav
else
else //seems this condition is never met
{
opts->audio_in_type = 0; //not sure if this works or needs to openPulse here
//opts->audio_in_type = 5; //not sure if this works or needs to openPulse here
fprintf(stderr, "Error, couldn't open input file.\n");
exit(1);
}
}
if (opts->split == 1)

View File

@@ -283,8 +283,8 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0;
//disabling again, causing issues with trunking
if (state->synctype == 1 && opts->p25_trunk == 1)
//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);
@@ -347,7 +347,7 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0;
//disabling again, causing issues with trunking
//disabling again, causing issues with trunking P25
if (state->synctype == 0 && opts->p25_trunk == 1)
{
// Use the P25 heuristics if available

View File

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

View File

@@ -231,10 +231,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
t_max = 12; //based on Frame_Sync_2 pattern
}
//if Phase 2 (or YSF in future), then only 19
//if Phase 2 (or YSF in future), then only 20
else if (state->lastsynctype == 35 || state->lastsynctype == 36) //P2
{
t_max = 19; //Phase 2 S-ISCH is only 19
t_max = 20;
}
else t_max = 24; //24 for everything else
@@ -1276,122 +1276,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
//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,33 +1286,30 @@ 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;
state->lastsynctype = 28;
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1) fprintf (stderr, "PANDF ");
// fprintf (stderr, " %s ", synctest19);
//if (opts->payload == 1) fprintf (stderr, "PANDF ");
return (28);
}
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;
state->lastsynctype = 29;
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1) fprintf (stderr, "PANDF ");
// fprintf (stderr, " %s ", synctest19);
//if (opts->payload == 1) fprintf (stderr, "PANDF ");
return (29);
}
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;
@@ -1435,8 +1317,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if (state->lastsynctype == 28)
{
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1) fprintf (stderr, "FSW ");
// fprintf (stderr, " %s ", synctest10);
//if (opts->payload == 1) fprintf (stderr, "FSW ");
return (28);
}
state->lastsynctype = 28; //need two consecutive patterns to continue
@@ -1445,7 +1326,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;
@@ -1453,8 +1334,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if (state->lastsynctype == 29)
{
state->last_cc_sync_time = time(NULL);
// if (opts->payload == 1) fprintf (stderr, "FSW ");
// fprintf (stderr, " %s ", synctest10);
//if (opts->payload == 1) fprintf (stderr, "FSW ");
return (29);
}
state->lastsynctype = 29; //need two consecutive patterns to continue
@@ -1462,95 +1342,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
}
#endif //NXDN Sync Type Selection
//Provoice Conventional -- Some False Positives due to shortened frame sync pattern, so use squelch if possible
#ifdef PVCONVENTIONAL
if (opts->frame_provoice == 1)
{
memset (synctest32, 0, sizeof(synctest32));
strncpy (synctest32, (synctest_p - 31), 16); //short sync grab here on 32
char pvc_txs[9]; //string (symbol) value of TX Address
char pvc_rxs[9]; //string (symbol) value of RX Address
uint8_t pvc_txa = 0; //actual value of TX Address
uint8_t pvc_rxa = 0; //actual value of RX Address
strncpy (pvc_txs, (synctest_p - 15), 8); //copy string value of TX Address
strncpy (pvc_rxs, (synctest_p - 7), 8); //copy string value of RX Address
if ((strcmp (synctest32, INV_PROVOICE_CONV_SHORT) == 0))
{
if (state->lastsynctype == 15) //use this condition, like NXDN, to migitage false positives due to short sync pattern
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "ProVoice ");
// fprintf (stderr, "Sync Pattern = %s ", synctest32);
// fprintf (stderr, "TX = %s ", pvc_txs);
// fprintf (stderr, "RX = %s ", pvc_rxs);
for (int i = 0; i < 8; i++)
{
pvc_txa = pvc_txa << 1;
pvc_rxa = pvc_rxa << 1;
//symbol 1 is binary 1 on inverted
//I hate working with strings, has to be a better way to evaluate this
memset (pvc_txs, 0, sizeof (pvc_txs));
memset (pvc_rxs, 0, sizeof (pvc_rxs));
strncpy (pvc_txs, (synctest_p - 15+i), 1);
strncpy (pvc_rxs, (synctest_p - 7+i), 1);
if ((strcmp (pvc_txs, "1") == 0))
pvc_txa = pvc_txa + 1;
if ((strcmp (pvc_rxs, "1") == 0))
pvc_rxa = pvc_rxa + 1;
}
printFrameSync (opts, state, "-PV_C ", synctest_pos + 1, modulation);
fprintf (stderr, "TX: %d ", pvc_txa);
fprintf (stderr, "RX: %d ", pvc_rxa);
if (pvc_txa == 172) fprintf (stderr, "ALL CALL ");
state->lastsynctype = 15;
return (15);
}
state->lastsynctype = 15;
}
else if ((strcmp (synctest32, PROVOICE_CONV_SHORT) == 0))
{
if (state->lastsynctype == 14) //use this condition, like NXDN, to migitage false positives due to short sync pattern
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "ProVoice ");
// fprintf (stderr, "Sync Pattern = %s ", synctest32);
// fprintf (stderr, "TX = %s ", pvc_txs);
// fprintf (stderr, "RX = %s ", pvc_rxs);
for (int i = 0; i < 8; i++)
{
pvc_txa = pvc_txa << 1;
pvc_rxa = pvc_rxa << 1;
//symbol 3 is binary 1 on positive
//I hate working with strings, has to be a better way to evaluate this
memset (pvc_txs, 0, sizeof (pvc_txs));
memset (pvc_rxs, 0, sizeof (pvc_rxs));
strncpy (pvc_txs, (synctest_p - 15+i), 1);
strncpy (pvc_rxs, (synctest_p - 7+i), 1);
if ((strcmp (pvc_txs, "3") == 0))
pvc_txa = pvc_txa + 1;
if ((strcmp (pvc_rxs, "3") == 0))
pvc_rxa = pvc_rxa + 1;
}
printFrameSync (opts, state, "+PV_C ", synctest_pos + 1, modulation);
fprintf (stderr, "TX: %d ", pvc_txa);
fprintf (stderr, "RX: %d ", pvc_rxa);
if (pvc_txa == 172) fprintf (stderr, "ALL CALL ");
state->lastsynctype = 14;
return (14);
}
state->lastsynctype = 14;
}
}
#endif //End Provoice Conventional
} // t >= 10
if (exitflag == 1)

View File

@@ -52,7 +52,7 @@ char * FM_banner[9] = {
" ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝",
" "
" 'Aero' Edition v2.0.0-84-gacd2b0b Windows 32-bit "
};
int comp (const void *a, const void *b)
@@ -77,6 +77,36 @@ void
noCarrier (dsd_opts * opts, dsd_state * state)
{
// // experimental conventional frequency scanner mode
// if (opts->scanner_mode == 1)
// {
// if (state->lcn_freq_roll > state->lcn_freq_count) //with >= we were cutting one short
// {
// state->lcn_freq_roll = 0; //reset to zero
// }
// //check that we have a non zero value first, then tune next frequency
// if (state->trunk_lcn_freq[state->lcn_freq_roll] != 0)
// {
// //rigctl
// if (opts->use_rigctl == 1)
// {
// 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
// if (opts->audio_in_type == 3)
// {
// rtl_udp_tune (opts, state, state->trunk_lcn_freq[state->lcn_freq_roll]);
// }
// if (state->lastsynctype != -1) fprintf (stderr, "Resume Scanning Mode\n");
// }
// state->lcn_freq_roll++;
// }
// //end experimental conventional frequency scanner mode
//experimental conventional frequency scanner mode
if (opts->scanner_mode == 1 && ( (time(NULL) - state->last_cc_sync_time) > opts->trunk_hangtime))
{
@@ -157,8 +187,6 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->p25_vc_freq[0] = 0;
state->p25_vc_freq[1] = 0;
memset(state->active_channel, 0, sizeof(state->active_channel));
state->is_con_plus = 0; //flag off
}
@@ -168,7 +196,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->dmr_payload_p = state->dibit_buf + 200;
memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
//dmr buffer end
//close MBE out files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
@@ -318,8 +346,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->fourv_counter[1] = 0;
//values displayed in ncurses terminal
// state->p25_vc_freq[0] = 0;
// state->p25_vc_freq[1] = 0;
state->p25_vc_freq[0] = 0;
state->p25_vc_freq[1] = 0;
//new nxdn stuff
state->nxdn_part_of_frame = 0;
@@ -332,18 +360,6 @@ noCarrier (dsd_opts * opts, dsd_state * state)
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
sprintf (state->nxdn_call_type, "%s", "");
//unload keys when using keylaoder
if (state->keyloader == 1)
{
state->R = 0; //NXDN
state->K = 0; //BP
state->K1 = 0; //tera 10 char BP
state->H = 0; //shim for above
}
//forcing key application will re-enable this at the time of voice tx
state->nxdn_cipher_type = 0;
//dmr overaching manufacturer in use for a particular system or radio
// state->dmr_mfid = -1;
@@ -357,7 +373,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
//initialize cap+ bits and block num storage
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
memset (state->cap_plus_block_num, 0, sizeof(state->cap_plus_block_num));
state->cap_plus_block_num = 0;
//init confirmed data individual block crc as invalid
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
@@ -375,13 +391,11 @@ noCarrier (dsd_opts * opts, dsd_state * state)
memset(state->dmr_embedded_gps, 0, sizeof(state->dmr_embedded_gps));
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
// memset(state->active_channel, 0, sizeof(state->active_channel));
//REMUS! multi-purpose call_string
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
if (time(NULL) - state->last_cc_sync_time > 10) //ten seconds of no carrier
if (time(NULL) - state->last_cc_sync_time > 30) //thirty seconds of no carrier
{
state->dmr_rest_channel = -1;
state->p25_vc_freq[0] = 0;
@@ -391,7 +405,6 @@ noCarrier (dsd_opts * opts, dsd_state * state)
sprintf(state->dmr_branding, "%s", "");
sprintf (state->dmr_site_parms, "%s", "");
opts->p25_is_tuned = 0;
memset(state->active_channel, 0, sizeof(state->active_channel));
}
opts->dPMR_next_part_of_superframe = 0;
@@ -423,11 +436,12 @@ initOpts (dsd_opts * opts)
opts->p25status = 0;
opts->p25tg = 0;
opts->scoperate = 15;
sprintf (opts->audio_in_dev, "pulse");
sprintf (opts->audio_in_dev, "/dev/dsp");
opts->audio_in_fd = -1;
sprintf (opts->audio_out_dev, "pulse");
sprintf (opts->audio_out_dev, "/dev/dsp");
opts->audio_out_fd = -1;
opts->audio_out_fdR = -1;
opts->split = 0;
opts->playoffset = 0;
@@ -519,10 +533,10 @@ initOpts (dsd_opts * opts)
opts->inverted_dpmr = 0;
opts->dmr_mono = 0;
opts->dmr_stereo = 1;
opts->aggressive_framesync = 1; //more aggressive to combat wonk wonk voice decoding
//see if initializing these values causes issues elsewhere, if so, then disable.
opts->audio_in_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
opts->audio_out_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
opts->aggressive_framesync = 1;
opts->audio_in_type = 5;
opts->audio_out_type = 5;
opts->lrrp_file_output = 0;
@@ -539,7 +553,7 @@ initOpts (dsd_opts * opts)
//rigctl options
opts->use_rigctl = 0;
opts->rigctl_sockfd = 0;
opts->rigctlportno = 4532; //TCP Port Number; GQRX - 7356; SDR++ - 4532
opts->rigctlportno = 7356; //TCP Port Number; GQRX - 7356; SDR++ - 4532
sprintf (opts->rigctlhostname, "%s", "localhost");
//udp input options
@@ -580,11 +594,14 @@ initOpts (dsd_opts * opts)
//Trunking - Tune Data Calls
opts->trunk_tune_data_calls = 0; //disabled by default
//Trunking - Tune Encrypted Calls (P25 only on applicable grants with svc opts)
opts->trunk_tune_enc_calls = 1; //enabled by default
opts->dPMR_next_part_of_superframe = 0;
//OSS audio - Slot Preference
//slot preference is used during OSS audio playback to
//prefer one tdma voice slot over another when both are playing back
//this is a fix to cygwin stuttering when both slots have voice
opts->slot_preference = 0; //default prefer slot 1 -- state->currentslot = 0;
//dsp structured file
opts->dsp_out_file[0] = 0;
opts->use_dsp_output = 0;
@@ -816,7 +833,7 @@ initState (dsd_state * state)
state->p25_cc_is_tdma = 2; //init on 2, TSBK NET_STS will set 0, TDMA NET_STS will set 1. //used to determine if we need to change symbol rate when cc hunting
//experimental symbol file capture read throttle
state->symbol_throttle = 0; //throttle speed
state->symbol_throttle = 100; //throttle speed
state->use_throttle = 0; //only use throttle if set to 1
state->p2_scramble_offset = 0;
@@ -826,7 +843,6 @@ initState (dsd_state * state)
state->p25_chan_iden = 0;
for (int i = 0; i < 16; i++)
{
state->p25_chan_tdma[i] = -1; //0, or -1
state->p25_chan_type[i] = 0;
state->p25_trans_off[i] = 0;
state->p25_chan_spac[i] = 0;
@@ -856,7 +872,6 @@ initState (dsd_state * state)
state->lcn_freq_roll = 0; //needs reset if sync is found?
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL);
state->last_active_time = time(NULL);
state->is_con_plus = 0;
//dmr trunking/ncurses stuff
@@ -877,7 +892,7 @@ initState (dsd_state * state)
state->nxdn_location_site_code = 0;
state->nxdn_location_sys_code = 0;
sprintf (state->nxdn_location_category, "%s", " ");
//channel access information
state->nxdn_rcn = 0;
state->nxdn_base_freq = 0;
@@ -886,7 +901,7 @@ initState (dsd_state * state)
//multi-key array
memset (state->rkey_array, 0, sizeof(state->rkey_array));
state->keyloader = 0; //keyloader off
state->keyloader = 0; //keyloader off
//Remus DMR End Call Alert Beep
state->dmr_end_alert[0] = 0;
@@ -899,10 +914,10 @@ initState (dsd_state * state)
//initialize unified dmr pdu 'superframe'
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
memset (state->data_header_valid, 0, sizeof(state->data_header_valid));
//initialize cap+ bits and block num storage
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
memset (state->cap_plus_block_num, 0, sizeof(state->cap_plus_block_num));
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
state->cap_plus_block_num = 0;
//init confirmed data individual block crc as invalid
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
@@ -920,7 +935,6 @@ initState (dsd_state * state)
memset(state->dmr_alias_block_segment, 0, sizeof(state->dmr_alias_block_segment));
memset(state->dmr_embedded_gps, 0, sizeof(state->dmr_embedded_gps));
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
memset(state->active_channel, 0, sizeof(state->active_channel));
//REMUS! multi-purpose call_string
sprintf (state->call_string[0], "%s", " "); //21 spaces
@@ -947,18 +961,18 @@ usage ()
{
printf ("\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 ("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 ("\n");
printf ("Display Options:\n");
printf (" -N Use NCurses Terminal\n");
printf (" dsd-fme -N 2> log.ans \n");
printf (" dsd-fme-aero -N 2> log.ans \n");
printf (" -Z Log MBE/PDU Payloads to console\n");
printf ("\n");
printf ("Input/Output options:\n");
printf (" -i <device> Audio input device (default is pulse audio)\n");
printf (" - for piped stdin\n");
printf (" -i <device> Audio input device (default is /dev/dsp)\n");
printf (" pulse for pulse audio \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");
@@ -966,8 +980,11 @@ usage ()
printf (" filename.wav for 48K/1 wav files (SDR++, GQRX)\n");
printf (" filename.wav -s 96000 for 96K/1 wav files (DSDPlus)\n");
printf (" (Use single quotes '/directory/audio file.wav' when directories/spaces are present)\n");
// printf (" (Windows - '\directory\audio file.wav' backslash, not forward slash)\n");
printf (" -s <rate> Sample Rate of wav input files (48000 or 96000) Mono only!\n");
printf (" -o <device> Audio output device (default is pulse audio)(null for no audio output)\n");
printf (" -o <device> Audio output device (default is /dev/dsp)\n");
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");
@@ -983,6 +1000,7 @@ usage ()
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 ("\n");
printf ("RTL-SDR options:\n");
printf (" WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>\n");
@@ -994,10 +1012,10 @@ usage ()
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 -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
printf (" Example: dsd-fme-aero -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
printf ("\n");
printf ("Decoder options:\n");
printf (" -fa Legacy Auto Detection 8k/1 (old methods default)\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");
@@ -1054,7 +1072,8 @@ usage ()
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 (" (dPMR and **tera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n");
printf (" -4 Force DMR Privacy Key over FID and SVC bits \n");
printf (" \n");
printf (" -4 Force Privacy Key over FID and SVC bits \n");
printf ("\n");
printf (" Trunking Options:\n");
printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n");
@@ -1077,8 +1096,8 @@ usage ()
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 ("\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:0:6020 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\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 ("\n");
exit (0);
}
@@ -1137,6 +1156,7 @@ if (opts->audio_in_type == 0)
if (opts->audio_out_type == 0)
{
// openPulseInput(opts); //test to see if we still randomly hang up in ncurses and tcp input if we open this and leave it opened
openPulseOutput(opts);
}
@@ -1263,8 +1283,9 @@ main (int argc, char **argv)
}
//fprintf (stderr,"%s", KNRM); //change back to normal
fprintf (stderr, "Github Build Version: %s \n", GIT_TAG);
fprintf (stderr,"MBElib version %s\n", versionstr);
// git_tag not working in 32-bit cygwin? or issue with copy and paste, even with the .git folder?
// fprintf (stderr, "Github Build Version: %s \n", GIT_TAG);
// fprintf (stderr,"MBElib version %s\n", versionstr);
initOpts (&opts);
initState (&state);
@@ -1273,7 +1294,7 @@ main (int argc, char **argv)
exitflag = 0;
while ((c = getopt (argc, argv, "haepPqs:t:v:zi: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:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
{
opterr = 0;
switch (c)
@@ -1285,7 +1306,7 @@ main (int argc, char **argv)
opts.call_alert = 1;
break;
//Free'd up switches include z
//Free'd up switches include
//make sure to put a colon : after each if they need an argument
//or remove colon if no argument required
@@ -1294,7 +1315,7 @@ main (int argc, char **argv)
opts.p25_trunk = 0; //turn off trunking mode if user enabled it
break;
case 'k': //multi-key loader
case 'k': //NXDN multi-key loader
strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0';
csvKeyImport(&opts, &state);
@@ -1318,6 +1339,13 @@ main (int argc, char **argv)
opts.use_dsp_output = 1;
break;
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 > 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':
@@ -1519,7 +1547,8 @@ main (int argc, char **argv)
case 'F':
opts.aggressive_framesync = 0;
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Pass/Fail\n");
//fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n");
fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
fprintf (stderr, "Relax DMR RAS/CRC CSBK/DATA Pass/Fail\n");
fprintf (stderr, "Relax NXDN SACCH/FACCH/CAC/F2U CRC Pass/Fail\n");
fprintf (stderr, "%s", KNRM);
@@ -1546,7 +1575,7 @@ main (int argc, char **argv)
// fprintf (stderr,"Writing mbe data temporarily disabled!\n");
break;
case 'c': //now is symbol capture bin output like FME Lite
case 'c':
strncpy(opts.symbol_out_file, optarg, 1023);
opts.symbol_out_file[1023] = '\0';
fprintf (stderr,"Writing + Appending symbol capture to file %s\n", opts.symbol_out_file);
@@ -1597,12 +1626,12 @@ main (int argc, char **argv)
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
opts.frame_ysf = 0;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_rate_out = 48000; // /dev/dsp does need this set to 48000 to properly process the upsampling
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 1;
opts.dmr_stereo = 1; //switching in 'stereo' for 'mono'
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 7000;
//opts.setmod_bw = 7000;
sprintf (opts.output_name, "Legacy Auto");
}
else if (optarg[0] == 'd')
@@ -1806,6 +1835,7 @@ main (int argc, char **argv)
opts.pulse_digi_rate_out = 24000;
opts.pulse_digi_out_channels = 2;
sprintf (opts.output_name, "DMR Stereo");
fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n");
}
else if (optarg[0] == 't')
@@ -1884,7 +1914,8 @@ main (int argc, char **argv)
// 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 or XDMA is highly encouraged.\n");
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo '-fs' or XDMA '-ft' is highly encouraged.\n");
}
else if (optarg[0] == 'm')
{
@@ -2094,12 +2125,14 @@ main (int argc, char **argv)
{
opts.audio_in_type = 8;
state.audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
fprintf (stderr, "TCP Connection Success!\n");
// openAudioInDevice(&opts); //do this to see if it makes it work correctly
}
else
{
opts.audio_in_type = 0;
opts.audio_in_type = 5;
fprintf (stderr, "TCP Connection Failure - Using Pulse Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "pulse");
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
}
}
@@ -2181,61 +2214,137 @@ main (int argc, char **argv)
if (rtl_ok == 0) //not set, means rtl support isn't compiled/available
{
fprintf (stderr, "RTL Support not enabled/compiled, falling back to Pulse Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "pulse");
opts.audio_in_type = 0;
fprintf (stderr, "RTL Support not enabled/compiled, falling back to OSS /dev/dsp Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
opts.audio_in_type = 5;
}
}
//still need to work out why I can't use this
//issues with samples received, may be using UDP DGRAMS incorrectly, incorrect procedure?
//doesn't work correctly, so just going to reroute to /dev/dsp instead
if((strncmp(opts.audio_in_dev, "udp", 3) == 0)) //udp socket input from SDR++, GQRX, and others
{
//also still needs err handling
opts.udp_sockfd = UDPBind(opts.udp_hostname, opts.udp_portno);
opts.audio_in_type = 6;
fprintf (stderr, "UDP Input not working, falling back to OSS /dev/dsp Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
opts.audio_in_type = 5;
}
if((strncmp(opts.audio_in_dev, "/dev/dsp", 8) == 0))
{
sprintf (opts.audio_in_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_in_type = 0;
}
int fmt;
int speed = 48000;
if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
{
sprintf (opts.audio_in_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_in_type = 0;
}
if((strncmp(opts.audio_out_dev, "/dev/dsp", 8) == 0))
{
sprintf (opts.audio_out_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_out_type = 0;
}
if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0))
{
sprintf (opts.audio_out_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_out_type = 0;
}
if((strncmp(opts.audio_out_dev, "pa", 2) == 0))
{
sprintf (opts.audio_out_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_out_type = 0;
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
fprintf (stderr, "Switching to /dev/dsp.\n");
}
if((strncmp(opts.audio_in_dev, "pa", 2) == 0))
{
sprintf (opts.audio_in_dev, "%s", "pulse");
fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_out_type = 0;
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
fprintf (stderr, "Switching to /dev/dsp.\n");
}
if((strncmp(opts.audio_in_dev, "/dev/dsp", 8) == 0))
{
fprintf (stderr, "OSS Input %s.\n", opts.audio_in_dev);
opts.audio_in_fd = open (opts.audio_in_dev, O_RDWR);
if (opts.audio_in_fd == -1)
{
fprintf (stderr, "Error, couldn't open %s\n", opts.audio_in_dev);
opts.audio_out = 0;
}
fmt = 0;
if (ioctl (opts.audio_in_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf (stderr, "ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts.audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf (stderr, "ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts.audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf (stderr, "ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts.audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf (stderr, "ioctl setfmt error \n");
}
opts.audio_in_type = 5; //5 will become OSS input type
}
if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0))
{
sprintf (opts.audio_out_dev, "%s", "/dev/dsp");
fprintf (stderr, "Switching to /dev/dsp.\n");
}
if((strncmp(opts.audio_out_dev, "pa", 2) == 0))
{
sprintf (opts.audio_out_dev, "%s", "/dev/dsp");
fprintf (stderr, "Switching to /dev/dsp.\n");
}
if((strncmp(opts.audio_out_dev, "/dev/dsp", 8) == 0))
{
fprintf (stderr, "OSS Output %s.\n", opts.audio_out_dev);
opts.audio_out_fd = open (opts.audio_out_dev, O_RDWR); //O_WRONLY
opts.audio_out_fdR = open (opts.audio_out_dev, O_RDWR);
if (opts.audio_out_fd == -1)
{
fprintf (stderr, "Error, couldn't open #1 %s\n", opts.audio_out_dev);
opts.audio_out = 0;
exit(1);
}
if (opts.audio_out_fdR == -1)
{
fprintf (stderr, "Error, couldn't open #2 %s\n", opts.audio_out_dev);
opts.audio_out = 0;
exit(1);
}
fmt = 0;
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf (stderr, "ioctl reset error \n");
}
if (ioctl (opts.audio_out_fdR, SNDCTL_DSP_RESET) < 0)
{
fprintf (stderr, "ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf (stderr, "ioctl speed error \n");
}
if (ioctl (opts.audio_out_fdR, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf (stderr, "ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf (stderr, "ioctl stereo error \n");
}
if (ioctl (opts.audio_out_fdR, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf (stderr, "ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf (stderr, "ioctl setfmt error \n");
}
if (ioctl (opts.audio_out_fdR, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf (stderr, "ioctl setfmt error \n");
}
opts.audio_out_type = 5; //5 will become OSS output type
}
if((strncmp(opts.audio_in_dev, "pulse", 5) == 0))
@@ -2261,14 +2370,15 @@ main (int argc, char **argv)
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);
}
{
openWavOutFile (&opts, &state);
}
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
if (opts.audio_out_type == 0) openPulseOutput(&opts); //need to open it up for output?
if (opts.audio_out_type == 5) openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
}
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
{
opts.split = 1;
@@ -2301,16 +2411,13 @@ main (int argc, char **argv)
if (opts.playfiles == 1)
{
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
openPulseOutput(&opts); //need to open it up for output
state.aout_gain = 25; //BUGFIX: No audio output when playing back .amb/.imb files
playMbeFiles (&opts, &state, argc, argv);
}
else
{
liveScanner (&opts, &state);
liveScanner (&opts, &state);
}
cleanupAndExit (&opts, &state);

View File

@@ -145,6 +145,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
uint8_t hash_bits[24];
memset (hash_bits, 0, sizeof(hash_bits));
int preempt = 0; //TDMA dual voice slot preemption(when using OSS output)
for (i = 0; i < 88; i++)
{
imbe_d[i] = 0;
@@ -215,16 +218,17 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//state->errs2 = state->errs;
mbe_demodulateImbe7100x4400Data (imbe7100_fr);
state->errs2 = mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d);
mbe_convertImbe7100to7200(imbe_d); //needs extra conversion step apparently
if (opts->payload == 1)
{
PrintIMBEData (opts, state, imbe_d);
}
mbe_convertImbe7100to7200(imbe_d);
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);
//below line the old way of doing this
// mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
if (opts->payload == 1)
{
PrintIMBEData (opts, state, imbe_d);
}
if (opts->mbe_out_f != NULL)
{
saveImbe4400Data (opts, state, imbe_d);
@@ -300,8 +304,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
if (state->M == 0)
{
//see if we need to hash a value larger than 16-bits
hash = state->lasttg & 0xFFFFFF;
// fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash);
hash = state->lasttg & 0xFFFFFF;
// fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash);
if (hash > 0xFFFF) //if greater than 16-bits
{
for (int i = 0; i < 24; i++)
@@ -608,6 +612,14 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
//end reverse mute test
//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)
{
opts->audio_out = 0;
preempt = 1;
if (opts->payload == 0) fprintf (stderr, " *MUTED*");
}
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
{
state->debug_audio_errors += state->errs2;
@@ -664,6 +676,14 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
//end reverse mute test
//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)
{
opts->audio_out = 0;
preempt = 1;
if (opts->payload == 0) fprintf (stderr, " *MUTED*");
}
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
{
state->debug_audio_errorsR += state->errs2R;
@@ -718,6 +738,12 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
}
if (preempt == 1)
{
opts->audio_out = 1;
preempt = 0;
}
//reset audio out flag for next repitition
if (strcmp(mode, "B") == 0) opts->audio_out = 1;
//restore flag for null output type

View File

@@ -97,9 +97,9 @@ char * SyncTypes[44] = {
"NXDN",
"YSF", //30
"YSF",
"DMR ", //DMR MS VOICE
"DMR ", //DMR MS DATA
"DMR ", //DMR RC DATA
"DMR",
"DMR",
"DMR",
"P25P2",
"P25P2",
"EDACS/PV", //37
@@ -125,7 +125,7 @@ char * DMRBusrtTypes[32] = {
"R-S ERR ",
"CRC ERR ",
"NULL ",
"Voice ",
"Voice ",
" ",
"INIT ",
"INIT ",
@@ -150,9 +150,10 @@ 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->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)
@@ -174,17 +175,20 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
//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);
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
if (opts->audio_out_type == 5) write (opts->audio_out_fd, buf, sizeof(buf));
//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);
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_outR, buf, sizeof(buf), NULL);
if (opts->audio_out_type == 5) write (opts->audio_out_fd, buf, sizeof(buf));
//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);
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
if (opts->audio_out_type == 5) write (opts->audio_out_fd, buf, sizeof(buf));
//fprintf (stderr, "BEEP 0 8\n");
}
@@ -199,7 +203,7 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
}
char * getDateN(void) {
char datename[99]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char datename[80]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char * curr2;
struct tm * to;
time_t t;
@@ -374,7 +378,7 @@ void ncursesOpen (dsd_opts * opts, dsd_state * state)
setlocale(LC_ALL, "");
initscr(); //Initialize NCURSES screen window
start_color();
#ifdef PRETTY_COLORS
init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style
init_pair(2, COLOR_RED, COLOR_BLACK); //Red for Terminated Calls
@@ -421,7 +425,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 5) //close UDP input SF file so we don't buffer audio while not decoding
{
sf_close(opts->udp_file_in); //disable for testing
// sf_close(opts->udp_file_in); //disable for testing
}
state->payload_keyid = 0;
@@ -847,8 +851,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if(opts->tcp_file_in == NULL)
{
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
sprintf (opts->audio_in_dev, "%s", "pulse");
opts->audio_in_type = 0;
if (opts->audio_out_type == 0)
{
sprintf (opts->audio_in_dev, "%s", "pulse");
opts->audio_in_type = 0;
}
else opts->audio_in_type = 5;
}
state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
@@ -978,7 +987,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
}
}
opts->audio_in_type = 0; //set after closing to prevent above crash condition
if (opts->audio_out_type == 0) opts->audio_in_type = 0; //set after closing to prevent above crash condition
else (opts->audio_in_type = 5);
choicec = 18; //exit
}
@@ -1674,7 +1684,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 5) //re-open UDP input 'file'
{
opts->udp_file_in = sf_open_fd(opts->udp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
// opts->udp_file_in = sf_open_fd(opts->udp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
}
//update sync time on cc sync so we don't immediately go CC hunting when exiting the menu
@@ -1692,8 +1702,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
{
timeout(0);
c = getch();
timeout(0); //
c = getch(); //
}
//use rtl_udp_tune
@@ -2063,7 +2073,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition %s \n", GIT_TAG);
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.0.0-84-gacd2b0b Win32");
}
if (opts->ncurses_compact == 0)
{
@@ -2073,8 +2083,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("%s", FM_bannerN[i]);
if (i == 1) printw (" ESC to Menu");
if (i == 2) printw (" 'q' to Quit ");
if (i == 5) printw (" MBElib %s", versionstr);
if (i == 6) printw (" %s \n", GIT_TAG);
if (i == 4) printw (" MBElib %s", versionstr);
if (i == 5) printw (" %s ", "Aero Win32"); //printw (" %s \n", GIT_TAG);
if (i == 6) printw (" %s \n", "v2.0.0-84-gacd2b0b"); //printw (" %s \n", GIT_TAG);
else printw ("\n");
}
attroff(COLOR_PAIR(6)); //6
@@ -2086,6 +2097,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{
printw ("| Pulse Audio Input: [%2i] kHz [%i] Channel\n", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels);
}
if (opts->audio_in_type == 5)
{
printw ("| OSS Audio Input: [%2i] kHz [1] Channel\n", SAMPLE_RATE_IN);
}
if (opts->audio_in_type == 4)
{
printw ("| Direct Symbol Bin Input: %s \n", opts->audio_in_dev);
@@ -2120,6 +2135,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n");
}
if (opts->audio_out_type == 5)
{
printw ("| OSS Audio Output: [%2i] kHz [1] Channel", SAMPLE_RATE_IN);
if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n");
}
if (opts->monitor_input_audio == 1)
{
printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n");
@@ -2149,10 +2170,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{
printw ("| RIGCTL Remote Control Client Established on Port [%d]\n", opts->rigctlportno);
}
#ifdef PRETTY_COLORS
if (opts->p25_trunk == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3) )
{
printw ("| Trunking -");
printw ("| Trunk Tracking Active -");
if (opts->trunk_tune_group_calls == 0) attron(COLOR_PAIR(2));
printw (" Group(g)");
attron(COLOR_PAIR(4));
@@ -2162,30 +2182,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->trunk_tune_data_calls == 0) attron(COLOR_PAIR(2));
printw (" Data(d)");
attron(COLOR_PAIR(4));
if (opts->trunk_tune_enc_calls == 0) attron(COLOR_PAIR(2));
printw (" Encrypted(e)");
attron(COLOR_PAIR(4));
printw (" Calls");
if (opts->trunk_use_allow_list == 1) printw (" - White List Mode\n");
else printw (" - Black List Mode\n");
}
#else //set on to UPPER CASE, off to lower case
if (opts->p25_trunk == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3) )
{
printw ("| Trunking -");
if (opts->trunk_tune_group_calls == 0) printw (" group(g)");
else printw (" GROUP(g)");
if (opts->trunk_tune_private_calls == 0) printw (" private(u)");
else printw (" PRIVATE(u)");
if (opts->trunk_tune_data_calls == 0) printw (" data(d)");
else printw (" DATA(d)");
if (opts->trunk_tune_enc_calls == 0) printw (" encrypted(e)");
else printw (" ENCRYPTED(e)");
printw (" Calls");
if (opts->trunk_use_allow_list == 1) printw (" - White List Mode\n");
else printw (" - Black List Mode\n");
}
#endif
if (opts->reverse_mute == 1)
{
printw ("| Reverse Mute - Muting Unencrypted Voice\n");
@@ -2197,14 +2197,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->K != 0) printw ("| Forcing Key Priority -- Moto BP Key: %03lld \n", state->K);
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 (opts->scanner_mode == 1)
{
printw ("| Fast Scan Mode Enabled ");
if (state->lcn_freq_roll != 0)
printw (" - Frequency: [%.06lf] Mhz", (double)state->trunk_lcn_freq[state->lcn_freq_roll-1]/1000000);
printw (" Speed: %.02lf sec \n", opts->trunk_hangtime); //not sure values less than 1 make a difference, may be system/environment dependent
}
printw (" Speed: %.02lf sec \n", opts->trunk_hangtime); //not sure values less than 1 make a difference, may be system/environment dependent
}
printw ("------------------------------------------------------------------------------\n");
attroff(COLOR_PAIR(4));
@@ -2326,28 +2326,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
printw ("]");
}
//Group Name Labels from CSV import
for (int k = 0; k < state->group_tally; k++)
{
if (state->group_array[k].groupNumber == tgn)
{
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 == src)
{
attron(COLOR_PAIR(4));
printw (" [%s]", state->group_array[k].groupName);
printw ("[%s] ", state->group_array[k].groupMode);
}
if (state->carrier == 1)
{
attron(COLOR_PAIR(3));
}
}
if (state->carrier == 1)
{
printw(" %s ", state->nxdn_call_type);
@@ -2396,24 +2374,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
//Active Trunking Channels (NXDN and IDAS)
if (1 == 1) //opts->p25_trunk
{
printw ("\n");
printw ("| ");
//active channel display
attron(COLOR_PAIR(4));
for (int i = 0; i < 16; i++)
{
if (state->active_channel[i] != 0) printw ("%s", state->active_channel[i]);
}
if (state->carrier == 1) attron(COLOR_PAIR(3));
else attroff(COLOR_PAIR(4));
}
printw("\n");
}
@@ -2498,6 +2458,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//This is the new one
printw ("%s | ", state->call_string[0]);
printw ("%s ", DMRBusrtTypes[state->dmrburstL]);
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
printw ("\n");
printw ("| V XTRA | "); //10 spaces
@@ -2587,31 +2548,27 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(3));
}
//Not always correct, or correct at all, depends on context
//this is already in the call_string anyways
// if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000
// {
// attron(COLOR_PAIR(2));
// printw (" **ENC** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
// if(state->dmrburstL == 16 && state->dmr_so == 0x80)
// {
// attron(COLOR_PAIR(2));
// printw (" **Emergency** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
// if(state->dmrburstL == 16 && state->dmr_so == 0x30) //0010 0000
// {
// attron(COLOR_PAIR(2));
// printw (" **Private Call** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000
{
attron(COLOR_PAIR(2));
printw (" **ENC** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
if(state->dmrburstL == 16 && state->dmr_so == 0x80)
{
attron(COLOR_PAIR(2));
printw (" **Emergency** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
if(state->dmrburstL == 16 && state->dmr_so == 0x30) //0010 0000
{
attron(COLOR_PAIR(2));
printw (" **Private Call** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
printw ("\n");
//printw ("| | "); //10 spaces
@@ -2619,7 +2576,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4));
if(state->dmrburstL == 16) //only during call
{
@@ -2645,7 +2601,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
//LRRP
if(state->dmrburstL != 16) //only during data and no trunking
if(state->dmrburstL != 16) //only during data and no trunking //&& opts->p25_trunk == 0
{
attron(COLOR_PAIR(4));
printw ("%s", state->dmr_lrrp_gps[0]);
@@ -2694,6 +2650,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//THIS IS THE NEW ONE
printw ("%s | ", state->call_string[1]);
printw ("%s ", DMRBusrtTypes[state->dmrburstR]);
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
printw ("\n");
printw ("| V XTRA | "); //10 spaces
@@ -2772,32 +2729,28 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("Hytera Full Encrypt");
attron(COLOR_PAIR(3));
}
//Not always correct, or correct at all, depends on context
//this is already in the call_string anyways
// if(state->dmrburstR == 16 && state->dmr_soR == 0x40 && state->R == 0) //0100 0000
// {
// attron(COLOR_PAIR(2));
// printw (" **ENC** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
// if(state->dmrburstR == 16 && state->dmr_soR == 0x80)
// {
// attron(COLOR_PAIR(2));
// printw (" **Emergency** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
// if(state->dmrburstR == 16 && state->dmr_soR == 0x30) //0010 0000
// {
// attron(COLOR_PAIR(2));
// printw (" **Private Call** ");
// attroff(COLOR_PAIR(2));
// attron(COLOR_PAIR(3));
// }
//Call Types, may switch to the more robust version later?
if(state->dmrburstR == 16 && state->dmr_soR == 0x40 && state->R == 0) //0100 0000
{
attron(COLOR_PAIR(2));
printw (" **ENC** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
if(state->dmrburstR == 16 && state->dmr_soR == 0x80)
{
attron(COLOR_PAIR(2));
printw (" **Emergency** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
if(state->dmrburstR == 16 && state->dmr_soR == 0x30) //0010 0000
{
attron(COLOR_PAIR(2));
printw (" **Private Call** ");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(3));
}
printw ("\n");
//printw ("| | ");
@@ -2805,7 +2758,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4));
if(state->dmrburstR == 16) //only during call
{
@@ -2831,7 +2783,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
//LRRP
if(state->dmrburstR != 16) //only during data and no trunking
if(state->dmrburstR != 16) //only during data and no trunking //&& opts->p25_trunk == 0
{
attron(COLOR_PAIR(4));
printw ("%s", state->dmr_lrrp_gps[1]);
@@ -2862,23 +2814,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (1 == 1) //opts->p25_trunk == 1
{
printw ("| | "); //Active Trunking Channels
//active channel display
attron(COLOR_PAIR(4));
for (int i = 0; i < 31; i++) //up to 31 idas channels
{
if (state->active_channel[i] != 0) printw ("%s", state->active_channel[i]);
}
if (state->carrier == 1) attron(COLOR_PAIR(3));
else attroff(COLOR_PAIR(4));
printw ("\n");
}
if (1 == 1) //opts->p25_trunk == 1
{
printw ("| | "); //Currently Tuned Frequency
printw ("| T INFO | ");
// Tuned Frequency Display
if (state->p25_vc_freq[0] != 0)
@@ -2890,7 +2826,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else attroff(COLOR_PAIR(4));
printw ("\n");
}
} // end if not MS
} //end DMR BS Types
@@ -3090,164 +3026,166 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
refresh();
//keyboard shortcuts - codes same as ascii codes
//keyboard shortcuts - codes same as ascii codes
if (c == 27) //esc key, open menu
{
ncursesMenu (opts, state); //just a quick test
}
{
ncursesMenu (opts, state); //just a quick test
}
if (c == 122) //'z' key, toggle payload to console
{
if (opts->payload == 1) opts->payload = 0;
else opts->payload = 1;
}
if (c == 122) //'z' key, toggle payload to console
{
if (opts->payload == 1) opts->payload = 0;
else opts->payload = 1;
}
if (c == 99) //'c' key, toggle compact mode
{
if (opts->ncurses_compact == 1) opts->ncurses_compact = 0;
else opts->ncurses_compact = 1;
}
if (c == 99) //'c' key, toggle compact mode
{
if (opts->ncurses_compact == 1) opts->ncurses_compact = 0;
else opts->ncurses_compact = 1;
}
if (c == 116) //'t' key, toggle trunking mode
{
if (opts->p25_trunk == 1) opts->p25_trunk = 0;
else opts->p25_trunk = 1;
opts->scanner_mode = 0; //turn off scanner mode
}
if (c == 116) //'t' key, toggle trunking
{
if (opts->p25_trunk == 1) opts->p25_trunk = 0;
else opts->p25_trunk = 1;
}
if (c == 121) //'y' key, toggle scanner mode
if (c == 121) //'y' key, toggle scanner mode
{
if (opts->scanner_mode == 1) opts->scanner_mode = 0;
else opts->scanner_mode = 1;
opts->p25_trunk = 0; //turn off trunking mode
}
if (c == 97) //'a' key, toggle call alert beep
{
if (opts->call_alert == 1) opts->call_alert = 0;
else opts->call_alert = 1;
}
if (c == 104) //'h' key, toggle history
{
if (opts->ncurses_history == 1) opts->ncurses_history = 0;
else opts->ncurses_history = 1;
}
if (c == 113) //'q' key, quit
{
ncursesClose();
cleanupAndExit (opts, state);
}
if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr)
{
if (state->M == 1) state->M = 0;
else state->M = 1;
}
if (c == 105) //'i' key, toggle signal inversion on inverted types
{
//Set all signal for inversion or uninversion
if (opts->inverted_dmr == 0)
if (c == 97) //'a' key, toggle call alert beep
{
opts->inverted_dmr = 1;
opts->inverted_dpmr = 1;
opts->inverted_x2tdma = 1;
opts->inverted_ysf = 1;
if (opts->call_alert == 1) opts->call_alert = 0;
else opts->call_alert = 1;
}
else
{
opts->inverted_dmr = 0;
opts->inverted_dpmr = 0;
opts->inverted_x2tdma = 0;
opts->inverted_ysf = 0;
}
}
if (c == 109) //'m' key, toggle qpsk/c4fm - everything but phase 2
{
if (state->rf_mod == 0)
if (c == 104) //'h' key, toggle history
{
opts->mod_c4fm = 0;
opts->mod_qpsk = 1;
opts->mod_gfsk = 0;
state->rf_mod = 1;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
if (opts->ncurses_history == 1) opts->ncurses_history = 0;
else opts->ncurses_history = 1;
}
else
{
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
}
if (c == 77) //'M' key, toggle qpsk - phase 2 6000 sps
{
if (state->rf_mod == 0)
if (c == 113) //'q' key, quit
{
opts->mod_c4fm = 0;
opts->mod_qpsk = 1;
opts->mod_gfsk = 0;
state->rf_mod = 1;
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
ncursesClose();
cleanupAndExit (opts, state);
}
else
{
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
}
if (c == 82) //'R', save symbol capture bin with date/time string as name
{
sprintf (opts->symbol_out_file, "%s %s.bin", getDateN(), getTimeN());
if (opts->symbol_out_file[0] != 0)
if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr)
{
opts->symbol_out = 1; //set flag to 1
openSymbolOutFile (opts, state);
if (state->M == 1) state->M = 0;
else state->M = 1;
}
}
if (c == 114) //'r' key, stop capturing symbol capture bin file
{
if (opts->symbol_out == 1)
if (c == 105) //'i' key, toggle signal inversion on inverted types
{
//Set all signal for inversion or uninversion
if (opts->inverted_dmr == 0)
{
opts->inverted_dmr = 1;
opts->inverted_dpmr = 1;
opts->inverted_x2tdma = 1;
opts->inverted_ysf = 1;
}
else
{
opts->inverted_dmr = 0;
opts->inverted_dpmr = 0;
opts->inverted_x2tdma = 0;
opts->inverted_ysf = 0;
}
}
if (c == 109) //'m' key, toggle qpsk/c4fm - everything but phase 2
{
if (state->rf_mod == 0)
{
opts->mod_c4fm = 0;
opts->mod_qpsk = 1;
opts->mod_gfsk = 0;
state->rf_mod = 1;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
else
{
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
}
if (c == 77) //'M' key, toggle qpsk - phase 2 6000 sps
{
if (state->rf_mod == 0)
{
opts->mod_c4fm = 0;
opts->mod_qpsk = 1;
opts->mod_gfsk = 0;
state->rf_mod = 1;
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
}
else
{
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
}
if (c == 82) //'R', save symbol capture bin with date/time string as name
{
sprintf (opts->symbol_out_file, "%s %s.bin", getDateN(), getTimeN());
if (opts->symbol_out_file[0] != 0)
{
fclose(opts->symbol_out_f);
sprintf (opts->audio_in_dev, "%s", opts->symbol_out_file);
opts->symbol_out = 1; //set flag to 1
openSymbolOutFile (opts, state);
}
}
opts->symbol_out = 0;
}
}
if (c == 114) //'r' key, stop capturing symbol capture bin file
{
if (opts->symbol_out == 1)
{
if (opts->symbol_out_file[0] != 0)
{
fclose(opts->symbol_out_f);
sprintf (opts->audio_in_dev, "%s", opts->symbol_out_file);
}
if (c == 32) //'space bar' replay last bin file (rework to do wav files too?)
{
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0)
{
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
goto SKIPR;
opts->symbol_out = 0;
}
}
if (S_ISREG(stat_buf.st_mode))
{
opts->symbolfile = fopen(opts->audio_in_dev, "r");
opts->audio_in_type = 4; //symbol capture bin files
}
SKIPR: ; //do nothing
}
//
// if (c == 32) //'space bar' replay last bin file (rework to do wav files too?)
// {
// struct stat stat_buf;
// if (stat(opts->audio_in_dev, &stat_buf) != 0)
// {
// fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
// goto SKIPR;
// }
// if (S_ISREG(stat_buf.st_mode))
// {
// opts->symbolfile = fopen(opts->audio_in_dev, "r");
// opts->audio_in_type = 4; //symbol capture bin files
// }
// SKIPR: ; //do nothing
// }
//
if (c == 80) //'P' key - start per call wav files
{
@@ -3280,26 +3218,32 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->dmr_stereo_wav = 0;
}
//
// if (c == 115) //'s' key, stop playing wav or symbol in files
// {
// if (opts->symbolfile != NULL)
// {
// if (opts->audio_in_type == 4)
// {
// fclose(opts->symbolfile);
// }
// }
if (c == 115) //'s' key, stop playing wav or symbol in files
{
if (opts->symbolfile != NULL)
{
if (opts->audio_in_type == 4)
{
fclose(opts->symbolfile);
}
}
if (opts->audio_in_type == 2) //wav input file
{
sf_close(opts->audio_in_file);
}
opts->audio_in_type = 0;
openPulseInput(opts);
}
// if (opts->audio_in_type == 2) //wav input file
// {
// sf_close(opts->audio_in_file);
// }
// if (opts->audio_out_type == 0)
// {
// opts->audio_in_type = 0;
// openPulseInput(opts);
// }
// else opts->audio_in_type = 5;//cleanupAndExit(opts, state);
// }
//
//test jumping back to CC on group lockout instead of random frequency to break framesync
if (state->lasttg != 0 && opts->frame_provoice != 1 && c == 49) //'1' key, lockout slot 1 or conventional tg from tuning/playback during session
{
@@ -3423,12 +3367,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else opts->trunk_tune_data_calls = 1;
}
if (opts->p25_trunk == 1 && c == 101) //'e' key, toggle tune enc calls (P25 only on certain grants)
{
if (opts->trunk_tune_enc_calls == 1) opts->trunk_tune_enc_calls = 0;
else opts->trunk_tune_enc_calls = 1;
}
if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls
{
if (opts->trunk_tune_group_calls == 1) opts->trunk_tune_group_calls = 0;
@@ -3480,48 +3418,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
noCarrier(opts, state);
}
//attempt retry to TCP Audio server
if (c == 56) // '8' key, try audio in type 8 (TCP Audio Server connection) using defaults OR whatever the user last specified
{
opts->tcp_sockfd = Connect(opts->tcp_hostname, opts->tcp_portno);
if (opts->tcp_sockfd != 0)
{
//reset audio input stream
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->samplerate=opts->wav_sample_rate;
opts->audio_in_file_info->channels=1;
opts->audio_in_file_info->seekable=0;
opts->audio_in_file_info->format=SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE;
opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
if(opts->tcp_file_in == NULL)
{
fprintf(stderr, "Error, couldn't Connect to TCP with libsndfile: %s\n", sf_strerror(NULL));
}
else
{
//close pulse input if it is currently open
if (opts->audio_in_type == 0) closePulseInput(opts);
fprintf (stderr, "TCP Socket Connected Successfully.\n");
opts->audio_in_type = 8;
}
}
else fprintf (stderr, "TCP Socket Connection Error.\n");
}
if (c == 57) //'9' key, try rigctl connection with default values
{
//use same or last specified host for TCP audio sink for connection
memcpy (opts->rigctlhostname, opts->tcp_hostname, sizeof (opts->rigctlhostname) );
opts->rigctl_sockfd = Connect(opts->rigctlhostname, opts->rigctlportno);
if (opts->rigctl_sockfd != 0) opts->use_rigctl = 1;
else opts->use_rigctl = 0;
}
//anything with an entry box will need the inputs and outputs stopped first
//so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those
//anything with an entry box will need the inputs and outputs stopped first
//so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those
} //end ncursesPrinter

View File

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

View File

@@ -49,14 +49,14 @@ static const unsigned int CNXDNConvolution_NUM_OF_STATES = 16U;
static const uint32_t CNXDNConvolution_M = 4U;
static const unsigned int CNXDNConvolution_K = 5U;
//NOTE:
static uint16_t m_metrics1[16U];
static uint16_t m_metrics2[16U];
static uint64_t m_decisions[300U]; //300
static uint16_t m_metrics1[16U] = {0};
static uint16_t m_metrics2[16U] = {0};
static uint64_t m_decisions[300U] = {0};
static uint16_t * m_oldMetrics = NULL;
static uint16_t * m_newMetrics = NULL;
static uint64_t * m_dp = NULL;
/* Functions ----------------------------------------------------------------*/
void CNXDNConvolution_decode(uint8_t s0, uint8_t s1)
@@ -158,15 +158,13 @@ void CNXDNConvolution_encode(const unsigned char* in, unsigned char* out, unsign
void CNXDNConvolution_start(void)
{
memset(m_metrics1, 0x00U, CNXDNConvolution_NUM_OF_STATES * sizeof(uint16_t));
memset(m_metrics2, 0x00U, CNXDNConvolution_NUM_OF_STATES * sizeof(uint16_t));
m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
memset(m_metrics1, 0x00U, sizeof(m_metrics1));
memset(m_metrics2, 0x00U, sizeof(m_metrics2));
memset(m_decisions, 0x00U, sizeof(m_decisions));
for (int x = 0; x < 4; x++) CNXDNConvolution_decode(0U, 0U);
}

View File

@@ -932,8 +932,7 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType)
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
state->nxdn_last_rid = 0;
state->nxdn_last_tg = 0;
state->nxdn_cipher_type = 0; //force will reactivate it if needed during voice tx
if (state->keyloader == 1) state->R = 0;
if (state->M == 0) state->nxdn_cipher_type = 0;
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
sprintf (state->nxdn_call_type, "%s", "");

View File

@@ -96,8 +96,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
//SRV_INFO
case 0x19:
state->nxdn_last_rid = 0;
state->nxdn_last_tg = 0;
NXDN_decode_srv_info(opts, state, ElementsContent);
break;
@@ -126,7 +124,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
//DISC
case 0x11:
NXDN_decode_VCALL(opts, state, ElementsContent);
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
//tune back to CC here - save about 1-2 seconds
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
@@ -137,7 +134,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
//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;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
@@ -149,7 +145,6 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
//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);
}
@@ -447,25 +442,17 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
if (state->nxdn_rcn == 1)
fprintf(stderr, "- DFA Channel [%04X][%05d] ", OFN, OFN);
//test VCALL_ASSGN_DUP, if no voice sync activity (by trunk_hangtime), then convert to assgn and allow tuning
//test VCALL_ASSGN_DUP, if no voice sync activity in 1-2 seconds, then convert to assgn and allow tuning
//VCALL_ASSGN_DUP has been seen in the middle of calls, but also on the tail end instead of a TX_REL or DISC
if (MessageType == 0x5 && opts->p25_is_tuned == 1 && opts->p25_trunk == 1)
{
if ( (time(NULL) - state->last_vc_sync_time) > opts->trunk_hangtime )
if ( (time(NULL) - state->last_vc_sync_time) > 1 )
{
MessageType = 0x04; //convert to VCALL
opts->p25_is_tuned = 0; //open tuning back up to tune
}
}
//assign active call to string (might place inside of tune decision to get multiple ones?)
if (state->nxdn_rcn == 0)
sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", Channel, DestinationID);
if (state->nxdn_rcn == 1)
sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", OFN, DestinationID);
state->last_active_time = time(NULL);
//Add support for tuning data and group/private calls on trunking systems
uint8_t tune = 0;
@@ -611,14 +598,14 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
void NXDN_decode_Alias(dsd_opts * opts, dsd_state * state, uint8_t * Message)
{
uint8_t Alias1 = 0x20; //value of an ascii 'space' character
uint8_t Alias2 = 0x20;
uint8_t Alias3 = 0x20;
uint8_t Alias4 = 0x20;
uint8_t Alias1 = 0x0; //value of an ascii 'NULL' character
uint8_t Alias2 = 0x0;
uint8_t Alias3 = 0x0;
uint8_t Alias4 = 0x0;
uint8_t blocknumber = 0;
uint8_t CrcCorrect = 0;
//alias can also hit on a facch1 -- do we still need this checkdown?
//alias can also hit on a facch1 so that would be with a non_sf_sacch attached
if (state->nxdn_sacch_non_superframe == FALSE)
{
CrcCorrect = state->NxdnElementsContent.VCallCrcIsGood;
@@ -633,25 +620,25 @@ void NXDN_decode_Alias(dsd_opts * opts, dsd_state * state, uint8_t * Message)
Alias3 = (uint8_t)ConvertBitIntoBytes(&Message[56], 8);
Alias4 = (uint8_t)ConvertBitIntoBytes(&Message[64], 8);
//sanity check to prevent OOB array assignment
if (blocknumber > 0 && blocknumber < 4) //last 'block' may have been assigning garbage name values -- needs testing
if (blocknumber > 0 && blocknumber < 5)
{
//assign to index -1, since block number conveyed here is 1,2,3,4, and index values are 0,1,2,3
//only assign if within valid range of ascii characters (not including diacritical extended alphabet)
//else assign "space" ascii character
//else assign "null" ascii character
//since we are zeroing out the blocks on tx_rel and other conditions, better to just set nothing to bad Alias bytes
//tends to zero out otherwise already good blocks set in a previous repitition.
if (Alias1 > 0x19 && Alias1 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", Alias1);
else ;// sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", 32); //space
else ;// sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", 0);
if (Alias2 > 0x19 && Alias2 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", Alias2);
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", 0); //space
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", 0);
if (Alias3 > 0x19 && Alias3 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", Alias3);
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", 0); //space
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", 0);
if (Alias4 > 0x19 && Alias4 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", Alias4);
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", 0); //space
else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", 0);
}
//crc errs in one repitition may occlude an otherwise good alias, so test and change if needed
@@ -808,12 +795,6 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
}
}
//clear stale active channel listing -- consider best placement for this (NXDN Type C Trunking -- inside SRV_INFO)
if ( (time(NULL) - state->last_active_time) > 3 )
{
memset (state->active_channel, 0, sizeof(state->active_channel));
}
}
void NXDN_decode_site_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
@@ -1125,44 +1106,6 @@ 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;
@@ -1221,14 +1164,14 @@ void NXDN_decode_VCALL_IV(dsd_opts * opts, dsd_state * state, uint8_t * Message)
{
uint32_t i;
state->payload_miN = 0; //zero out
unsigned long long int IV = 0;
uint64_t IV = 0;
//NOTE: On Type-D systems, the FACCH1 version of message only carries a 4-octet payload and also only carries a 22-bit IV
//which makes no sense since you still have the full 80-bits of FACCH1 to use
uint8_t idas = 0;
if (strcmp (state->nxdn_location_category, "Type-D") == 0) idas = 1;
if (!idas) IV = (unsigned long long int)ConvertBitIntoBytes(&Message[8], 64);
else IV = (unsigned long long int)ConvertBitIntoBytes(&Message[8], 22);
if (!idas) IV = (uint64_t)ConvertBitIntoBytes(&Message[8], 64);
else IV = (uint64_t)ConvertBitIntoBytes(&Message[8], 22);
//At this point, I would assume an LFSR function is needed to expand the 22-bit IV collected here into a 64-bit IV, or 128-bit IV
state->payload_miN = IV;
@@ -1272,11 +1215,11 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
uint8_t gu = Message[24]; //group or unit bit
//OSM 2 and 3 elements -- unique only
unsigned long long int iv_a = (uint64_t)ConvertBitIntoBytes(&Message[13], 12); //initialization vector (0-11)
uint64_t iv_a = (uint64_t)ConvertBitIntoBytes(&Message[13], 12); //initialization vector (0-11)
//OSM 1 elements -- unique only -- DOUBLE CHECK ALL OF THESE!
unsigned long long int iv_b = (uint64_t)ConvertBitIntoBytes(&Message[18], 6); //initialization vector (b12-17)
unsigned long long int iv_c = (uint64_t)ConvertBitIntoBytes(&Message[8], 5); //initialization vector (b18-22)
uint64_t iv_b = (uint64_t)ConvertBitIntoBytes(&Message[18], 6); //initialization vector (b12-17)
uint64_t iv_c = (uint64_t)ConvertBitIntoBytes(&Message[8], 5); //initialization vector (b18-22)
uint8_t iv_type = Message[24]; //0 or 1 tells us whether or not this is for IV, or for cipher/key
uint8_t call_opt = (uint8_t)ConvertBitIntoBytes(&Message[13], 3); //Call Options
uint8_t key_id = (uint8_t)ConvertBitIntoBytes(&Message[18], 6); //Key ID
@@ -1302,20 +1245,12 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
//OSM messages
if (opcode == 0x4 || opcode == 0x0) //INFO 4
{
//clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?)
if ( (time(NULL) - state->last_active_time) > 3 )
{
memset (state->active_channel, 0, sizeof(state->active_channel));
}
if (id == 2046)
{
fprintf (stderr, "Idle Repeater Message - ");
fprintf (stderr, "Area: %d; ", area);
fprintf (stderr, "Repeater 1: %d; ", rep1);
fprintf (stderr, "Repeater 2: %d; ", rep2);
sprintf (state->active_channel[rep1], "%s", "");
sprintf (state->active_channel[rep2], "%s", "");
}
else if (id == 2045)
@@ -1380,14 +1315,6 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (rep1 == 31) fprintf (stderr, "Termination ");
//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
state->last_active_time = time(NULL);
}
//start tuning section here
uint8_t tune = 0; //use this to check to see if okay to tune
@@ -1487,7 +1414,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (id == 31)
{
fprintf (stderr, "\n%s ", KYEL);
fprintf (stderr, " Call IV A: %04llX", iv_a);
fprintf (stderr, " Call IV A: %04lX", iv_a);
}
else
{
@@ -1509,7 +1436,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (id == 31)
{
fprintf (stderr, "\n%s ", KYEL);
fprintf (stderr, " Call IV A: %04llX; ", iv_a); //MSB 0-11
fprintf (stderr, " Call IV A: %04lX; ", iv_a); //MSB 0-11
//zero out IV storage and append this chunk to MSB position
state->payload_miN = 0;
state->payload_miN = state->payload_miN | (iv_a << 11); //MSB 11, so shift 11 (22 total bits).
@@ -1549,8 +1476,8 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
else
{
fprintf (stderr, "\n%s ", KYEL);
fprintf (stderr, "Call IV B: %04llX; ", iv_b);
fprintf (stderr, "Call IV C: %04llX; ", iv_c);
fprintf (stderr, "Call IV B: %04lX; ", iv_b);
fprintf (stderr, "Call IV C: %04lX; ", iv_c);
//Append to Call IV storage
state->payload_miN = state->payload_miN | (iv_c << 6); //middle 5 bits..shifts 6 to accomodate last 6 bits below
state->payload_miN = state->payload_miN | (iv_b << 0); //last 6 bits...no shift needed

View File

@@ -97,7 +97,6 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
lich = lich >> 1;
if (lich_parity_received != lich_parity_computed)
{
if (opts->payload == 1) fprintf(stderr, " Lich Parity Error %02X\n", lich);
state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly
goto END;
}
@@ -238,10 +237,6 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
break;
} // end of switch(lich)
//enable these after good lich parity and known lich value
state->carrier = 1;
state->last_cc_sync_time = time(NULL);
//printframesync after determining we have a good lich and it has something in it
if (idas)
{
@@ -348,54 +343,6 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
// else if (lich_fc == 3) fprintf (stderr, "SF SACCH/IDLE ");
// }
#ifdef LIMAZULUTWEAKS
//LimaZulu specific tweak, load keys from frequency value, if avalable -- test before VCALL
//needs to be loaded here, if superframe data pair, then we need to run the LFSR on it as well
if (voice) //can this run TOO frequently?
{
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", KYEL);
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];
if (state->R != 0 && state->M == 1) state->nxdn_cipher_type = 0x1;
//add additional time to last_sync_time for LimaZulu to hold on current frequency
//a little longer without affecting normal scan time on trunk_hangtime variable
state->last_cc_sync_time = time(NULL) + 2; //ask him for an ideal wait timer
}
#endif //end LIMAZULUTWEAKS
//Option/Steal Flags echoed in Voice, V+F, or Data
if (voice && !facch) //voice only, no facch steal
{

View File

@@ -1,11 +1,3 @@
/*-------------------------------------------------------------------------------
* p25_lcw.c
* P25p1 Link Control Word Decoding
*
* LWVMOBILE
* 2023-05 DSD-FME Florida Man Edition
*-----------------------------------------------------------------------------*/
#include "dsd.h"
//new p25_lcw function here -- TIA-102.AABF-D LCW Format Messages (if anybody wants to fill the rest out)
@@ -101,15 +93,13 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
if (channel1 && group1)
{
fprintf (stderr, "Ch: %04X TG: %d; ", channel1, group1);
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; ", channel1, group1);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[0], "Active Ch: %04X TG: %d;", channel1, group1);
}
if (channel2 && group2 && group1 != group2)
{
fprintf (stderr, "Ch: %04X TG: %d; ", channel2, group2);
sprintf (state->active_channel[1], "Active Ch: %04X TG: %d; ", channel2, group2);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[1], "Active Ch: %04X TG: %d;", channel2, group2);
}
}
@@ -309,8 +299,8 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
sprintf (state->dmr_lrrp_gps[0], "%s", ""); //this is used for active ch in p25 trunking
sprintf (state->dmr_lrrp_gps[1], "%s", ""); //this is used for active ch in p25 trunking
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
@@ -327,8 +317,8 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
sprintf (state->dmr_lrrp_gps[0], "%s", ""); //this is used for active ch in p25 trunking
sprintf (state->dmr_lrrp_gps[1], "%s", ""); //this is used for active ch in p25 trunking
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);

View File

@@ -24,16 +24,6 @@ static uint32_t crc32mbf(uint8_t buf[], int len)
void processMPDU(dsd_opts * opts, dsd_state * state)
{
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
//clear stale Active Channel messages here
if ( (time(NULL) - state->last_active_time) > 3 )
{
memset (state->active_channel, 0, sizeof(state->active_channel));
}
int tsbkbit[196]; //tsbk bit array, 196 trellis encoded bits
int tsbk_dibit[98];
@@ -286,33 +276,21 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
//Group Voice Channel Grant - Extended
else if (opcode == 0x0)
{
int svc = mpdu_byte[8];
int svc = mpdu_byte[8]; //look up what these do!
int channelt = (mpdu_byte[14] << 8) | mpdu_byte[15];
int channelr = (mpdu_byte[16] << 8) | mpdu_byte[17];
long int source = (mpdu_byte[3] << 16) |(mpdu_byte[4] << 8) | mpdu_byte[5];
int group = (mpdu_byte[18] << 8) | mpdu_byte[19];
long int freq1 = 0;
long int freq2 = 0;
fprintf (stderr, "%s\n ",KYEL);
if (svc & 0x80) fprintf (stderr, " Emergency");
if (svc & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc & 0x20) fprintf (stderr, " Duplex");
if (svc & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc & 0x7); //call priority
}
fprintf (stderr, " Group Voice Channel Grant Update - Extended");
fprintf (stderr, "%s",KYEL);
fprintf (stderr, "\n Group Voice Channel Grant Update - Extended");
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc, channelt, channelr, group, group);
freq1 = process_channel_to_freq (opts, state, channelt);
freq2 = process_channel_to_freq (opts, state, channelr);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d ", channelt, group);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[0], "Active Ch: %04X TG: %d", channelt, group);
for (int i = 0; i < state->group_tally; i++)
{
@@ -327,9 +305,6 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (svc & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
//tune if tuning available
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0))
{
@@ -353,7 +328,6 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
SetFreq(opts->rigctl_sockfd, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
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
else if (opts->audio_in_type == 3)
@@ -361,7 +335,6 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
rtl_udp_tune (opts, state, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}
@@ -371,7 +344,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
else if (opcode == 0x6)
{
//I'm not doing EVERY element of this, just enough for tuning!
int svc = mpdu_byte[8];
int svc = mpdu_byte[8]; //look up what these do!
int channelt = (mpdu_byte[22] << 8) | mpdu_byte[23];
int channelr = (mpdu_byte[24] << 8) | mpdu_byte[25]; //optional!
//using source and target address, not source and target id (is this correct?)
@@ -379,25 +352,14 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
long int target = (mpdu_byte[19] << 16) |(mpdu_byte[20] << 8) | mpdu_byte[21];
long int freq1 = 0;
long int freq2 = 0;
fprintf (stderr, "%s\n ",KYEL);
if (svc & 0x80) fprintf (stderr, " Emergency");
if (svc & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc & 0x20) fprintf (stderr, " Duplex");
if (svc & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc & 0x7); //call priority
}
fprintf (stderr, " Unit to Unit Voice Channel Grant Update - Extended");
fprintf (stderr, "%s",KYEL);
fprintf (stderr, "\n Unit to Unit Voice Channel Grant Update - Extended");
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Source [%ld][%04lX] Target [%ld][%04lX]", svc, channelt, channelr, source, source, target, target);
freq1 = process_channel_to_freq (opts, state, channelt);
freq2 = process_channel_to_freq (opts, state, channelr); //optional!
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TGT: %ld; ", channelt, target);
sprintf (state->dmr_lrrp_gps[0], "Active Ch: %04X TGT: %ld;", channelt, target);
for (int i = 0; i < state->group_tally; i++)
{
@@ -412,9 +374,6 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
//Skip tuning private calls if group calls are disabled
if (opts->trunk_tune_private_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (svc & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
//tune if tuning available
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0))
{
@@ -437,8 +396,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
}
//rtl_udp
else if (opts->audio_in_type == 3)
@@ -446,7 +404,6 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
rtl_udp_tune (opts, state, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}

View File

@@ -10,16 +10,6 @@
void processTSBK(dsd_opts * opts, dsd_state * state)
{
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
//clear stale Active Channel messages here
if ( (time(NULL) - state->last_active_time) > 3 )
{
memset (state->active_channel, 0, sizeof(state->active_channel));
}
int tsbkbit[196]; //tsbk bit array, 196 trellis encoded bits
int tsbk_dibit[98];
@@ -48,7 +38,11 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
int protectbit = 0;
int MFID = 0xFF; //Manufacturer ID - Might be beneficial to NOT send anything but standard 0x00 or 0x01 messages
//Update: Identified Bug in skipdibit incrememnt causing many block deinterleave/crc failures
//with correct values set, now we are decoding many more TSBKs
//TODO: Don't Print TSBKs/vPDUs unless verbosity levels set higher
//TSBKs are always single block, but up to three can be transmitted in a row,
//Multi-Block PDUs are sent on a different DUID - 0xC (not handled currently)
//collect three reps of 101 dibits (98 valid dibits with status dibits interlaced)
for (j = 0; j < 3; j++)
@@ -69,7 +63,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
if (i+(j*101) == skipdibit)
{
skipdibit += 36;
skipdibit += 36; //was set to 35, this was the bug
}
}

View File

@@ -475,6 +475,10 @@ void process_4V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n");
}
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
@@ -626,6 +630,10 @@ void process_2V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n");
}
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
@@ -711,7 +719,6 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
{
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine
}
if (duid_decoded == 0)
@@ -831,7 +838,7 @@ void processP2 (dsd_opts * opts, dsd_state * state)
p2_dibit_buffer (opts, state);
//look at our ISCH values and determine location in superframe before running frame scramble
for (framing_counter = 0; framing_counter < 4; framing_counter++)
for (framing_counter = 0; framing_counter < 4; framing_counter++)
{
//run ISCH in here so we know when to start descramble offset
process_ISCH (opts, state);
@@ -850,6 +857,16 @@ void processP2 (dsd_opts * opts, dsd_state * state)
//process DUID will run through all collected frames and handle them appropriately
process_P2_DUID (opts, state);
state->dmr_stereo = 0;
state->p2_is_lcch = 0;
state->p2_is_lcch = 0;
//bugfix for OSS dmrbust 16 shim, reset both to 0 upon exit
//in case or marginal signal and both get stuck on 16, indefinitely muting the non-preferred slot
//but...this can also cause at least one 4v/2v to get through on the other slot if the sync lines up that way
if (opts->audio_out_type == 5)
{
//set both to blank value
state->dmrburstL = 17;
state->dmrburstR = 17;
}
fprintf (stderr, "\n");
}

View File

@@ -97,8 +97,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
freq = process_channel_to_freq (opts, state, channel);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; ", channel, sgroup);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X SG: %d;", channel, sgroup);
for (int i = 0; i < state->group_tally; i++)
{
@@ -145,8 +144,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
}
//rtl_udp
else if (opts->audio_in_type == 3)
@@ -154,7 +152,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}
@@ -182,8 +179,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
freq = process_channel_to_freq (opts, state, channel);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d ", channel, sgroup);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X SG: %d", channel, sgroup);
for (int i = 0; i < state->group_tally; i++)
{
@@ -229,8 +225,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
}
//rtl_udp
else if (opts->audio_in_type == 3)
@@ -238,7 +233,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}
@@ -273,8 +267,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
freq2 = process_channel_to_freq (opts, state, channel2);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; Ch: %04X SG: %d; ", channel1, group1, channel2, group2);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X SG: %d; Ch: %04X SG: %d;", channel1, group1, channel2, group2);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
@@ -348,8 +341,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
SetFreq(opts->rigctl_sockfd, 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; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
j = 8; //break loop
}
@@ -359,7 +351,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, 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
}
}
@@ -389,26 +380,12 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
int source = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a];
long int freq = 0;
fprintf (stderr, "\n");
if (svc & 0x80) fprintf (stderr, " Emergency");
if (svc & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc & 0x20) fprintf (stderr, " Duplex");
if (svc & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc & 0x7); //call priority
}
fprintf (stderr, " Group Voice Channel Grant Update");
fprintf (stderr, "\n Group Voice Channel Grant Update");
fprintf (stderr, "\n SVC [%02X] CHAN [%04X] Group [%d] Source [%d]", svc, channel, group, source);
freq = process_channel_to_freq (opts, state, channel);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; ", channel, group);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X TG: %d;", channel, group);
for (int i = 0; i < state->group_tally; i++)
{
@@ -422,9 +399,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (svc & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
//tune if tuning available
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0))
{
@@ -459,7 +433,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
SetFreq(opts->rigctl_sockfd, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
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
else if (opts->audio_in_type == 3)
@@ -467,7 +440,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}
@@ -499,15 +471,11 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
freq = process_channel_to_freq (opts, state, channel);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TGT: %d; ", channel, target);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X TGT: %d;", channel, target);
//Skip tuning private calls if private calls is disabled
if (opts->trunk_tune_private_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled -- abb formats do not carry svc bits :(
if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
//unit to unit needs work, may fail under certain conditions (first blocked, second allowed, etc) (labels should still work though)
for (int i = 0; i < state->group_tally; i++)
{
@@ -551,8 +519,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq);
if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
}
//rtl_udp
else if (opts->audio_in_type == 3)
@@ -560,7 +527,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, 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);
}
}
}
@@ -592,46 +558,20 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
long int freq1r = 0;
long int freq2t = 0;
long int freq2r = 0;
fprintf (stderr, "\n Group Voice Channel Grant Update Multiple - Explicit");
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc1, channelt1, channelr1, group1, group1);
if (svc1 & 0x80) fprintf (stderr, " Emergency");
if (svc1 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc1 & 0x20) fprintf (stderr, " Duplex");
if (svc1 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc1 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc1 & 0x7); //call priority
}
freq1t = process_channel_to_freq (opts, state, channelt1);
if (channelr1 != 0 && channelr1 != 0xFFFF) freq1r = process_channel_to_freq (opts, state, channelr1);
freq1r = process_channel_to_freq (opts, state, channelr1);
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc2, channelt2, channelr2, group2, group2);
if (svc2 & 0x80) fprintf (stderr, " Emergency");
if (svc2 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc2 & 0x20) fprintf (stderr, " Duplex");
if (svc2 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc2 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc2 & 0x7); //call priority
}
freq1t = process_channel_to_freq (opts, state, channelt2);
if (channelr2 != 0 && channelr2 != 0xFFFF) freq1r = process_channel_to_freq (opts, state, channelr2);
freq1r = process_channel_to_freq (opts, state, channelr2);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channelt1, group1, channelt2, group2);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X TG: %d; Ch: %04X TG: %d;", channelt1, group1, channelt2, group2);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (svc1 & 0x40) && (svc2 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
int loop = 1;
if (channelt2 == channelt2) loop = 1;
else loop = 2;
@@ -642,16 +582,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
for (int j = 0; j < loop; j++)
{
//test svc opts for enc to tune or skip
if (j == 0)
{
if ( (svc1 & 0x40) && opts->trunk_tune_enc_calls == 0) j++; //skip to next
}
if (j == 1)
{
if (( svc2 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //skip to end
}
//assign our internal variables for check down on if to tune one freq/group or not
if (j == 0)
{
@@ -706,8 +636,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, tunable_freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
j = 8; //break loop
}
//rtl_udp
@@ -716,7 +645,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, 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
}
}
@@ -752,54 +680,18 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
fprintf (stderr, "\n Group Voice Channel Grant Update Multiple - Implicit");
fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1);
if (so1 & 0x80) fprintf (stderr, " Emergency");
if (so1 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (so1 & 0x20) fprintf (stderr, " Duplex");
if (so1 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so1 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so1 & 0x7); //call priority
}
freq1 = process_channel_to_freq (opts, state, channel1);
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
if (so2 & 0x80) fprintf (stderr, " Emergency");
if (so2 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (so2 & 0x20) fprintf (stderr, " Duplex");
if (so2 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so2 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so2 & 0x7); //call priority
}
freq2 = process_channel_to_freq (opts, state, channel2);
fprintf (stderr, "\n Channel 3 [%04X] Group 3 [%d][%04X]", channel3, group3, group3);
if (so3 & 0x80) fprintf (stderr, " Emergency");
if (so3 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (so3 & 0x20) fprintf (stderr, " Duplex");
if (so3 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so3 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so3 & 0x7); //call priority
}
freq3 = process_channel_to_freq (opts, state, channel3);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2, channel3, group3);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; Ch: %04X TG: %d;", channel1, group1, channel2, group2, channel3, group3);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (so1 & 0x40) && (so2 & 0x40) && (so3 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
int loop = 3;
long int tunable_freq = 0;
@@ -808,20 +700,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
for (int j = 0; j < loop; j++)
{
//test svc opts for enc to tune or skip
if (j == 0)
{
if ( (so1 & 0x40) && opts->trunk_tune_enc_calls == 0) j++; //skip to next
}
if (j == 1)
{
if ( (so2 & 0x40) && opts->trunk_tune_enc_calls == 0) j++; //skip to next
}
if (j == 2)
{
if ( (so3 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //skip to end
}
//assign our internal variables for check down on if to tune one freq/group or not
if (j == 0)
{
@@ -885,8 +763,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
SetFreq(opts->rigctl_sockfd, 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; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
j = 8; //break loop
}
//rtl_udp
@@ -896,7 +773,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//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
}
}
@@ -931,15 +807,11 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
freq2 = process_channel_to_freq (opts, state, channel2);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2);
state->last_active_time = time(NULL);
sprintf (state->dmr_lrrp_gps[slot], "Active Ch: %04X TG: %d; Ch: %04X TG: %d;", channel1, group1, channel2, group2);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled -- abb formats do not carry svc bits :(
if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
int loop = 1;
if (channel1 == channel2) loop = 1;
else loop = 2;
@@ -1008,7 +880,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//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; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL);
j = 8; //break loop
}
//rtl_udp
@@ -1018,7 +889,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//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
}
}
@@ -1046,23 +916,10 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
long int freq1 = 0;
long int freq2 = 0;
fprintf (stderr, "\n");
if (svc & 0x80) fprintf (stderr, " Emergency");
if (svc & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (svc & 0x20) fprintf (stderr, " Duplex");
if (svc & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", svc & 0x7); //call priority
}
fprintf (stderr, " Group Voice Channel Grant Update - Explicit");
fprintf (stderr, "\n Group Voice Channel Grant Update - Explicit");
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc, channelt, channelr, group, group);
freq1 = process_channel_to_freq (opts, state, channelt);
if (channelr != 0 && channelr != 0xFFFF) freq2 = process_channel_to_freq (opts, state, channelr); //one system had this as channel 0xFFFF -- look up any particular meaning for that
freq2 = process_channel_to_freq (opts, state, channelr);
//don't set the tg here, one multiple grant updates, will mess up the TG value on current call
// if (slot == 0)
@@ -1083,9 +940,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (svc & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
//tune if tuning available
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0))
{
@@ -1119,8 +973,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
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);
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
}
//rtl_udp
else if (opts->audio_in_type == 3)
@@ -1128,7 +981,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
rtl_udp_tune (opts, state, freq1);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1;
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
}
}
}
@@ -1366,7 +1218,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
{
fprintf (stderr, "\n Secondary Control Channel Broadcast - Explicit\n");
fprintf (stderr, " RFSS [%03d] SITE ID [%03X] CHAN-T [%04X] CHAN-R [%04X] SSC [%02X]", rfssid, siteid, channelt, channelr, sysclass);
fprintf (stderr, " RFSS[%03d] SITE ID [%03X] CHAN-T [%04X] CHAN-R [%04X] SSC [%02X]", rfssid, siteid, channelt, channelr, sysclass);
process_channel_to_freq (opts, state, channelt);
process_channel_to_freq (opts, state, channelr);

View File

@@ -245,11 +245,13 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces
}
if (opcode == 0x4 && err == 0)
{
if (state->currentslot == 1) state->dmrburstL = 21;
else state->dmrburstR = 21;
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
//if (state->currentslot == 1) state->dmrburstL = 21;
//else state->dmrburstR = 21;
fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC);
@@ -498,14 +500,16 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
//blank the call string here
//blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces
}
if (opcode == 0x4 && err == 0)
{
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
//if (state->currentslot == 0) state->dmrburstL = 21;
//else state->dmrburstR = 21;
fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC);

View File

@@ -1,432 +1,584 @@
#include "dsd.h"
#include "provoice_const.h"
// #define PVDEBUG
void processProVoice (dsd_opts * opts, dsd_state * state)
void
processProVoice (dsd_opts * opts, dsd_state * state)
{
int i, j, dibit;
int i, j, dibit, k;
uint8_t lid[80];
uint8_t lidbyte[10];
uint8_t init[64];
uint8_t initbyte[8];
char imbe7100_fr1[7][24];
char imbe7100_fr2[7][24];
const int *w, *x;
//raw bits storage for analysis
uint8_t raw_bits[800];
memset (raw_bits, 0, sizeof(raw_bits));
//raw bytes storage for analysis
uint8_t raw_bytes[100];
memset (raw_bytes, 0, sizeof(raw_bytes));
unsigned long long int initial = 0; //initial 64-bits before the lid
uint16_t lid = 0; //lid value 16-bit
unsigned long long int secondary = 0; //secondary 64-bits after lid, before voice
uint8_t spacer_bit[8]; //check this value to see if its a status thing (like P25 P1)
memset (spacer_bit, 0, sizeof (spacer_bit));
uint8_t spacer = 0;
uint16_t bf = 0; //the 16-bit value in-between imbe 2 and imbe 3 that is usually 2175
fprintf (stderr," VOICE");
//print group and source values if EA trunked
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && state->ea_mode == 1)
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Site: %lld Group: %d Source: %d LCN: %d ",
state->edacs_site_id, state->lasttg, state->lastsrc, state->edacs_tuned_lcn);
fprintf (stderr, "%s", KNRM);
}
//print afs value if standard/networked trunked
else if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && state->ea_mode == 0)
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Site: %lld AFS: %d-%d LCN: %d ",
state->edacs_site_id, (state->lasttg >> 7) & 0xF, state->lasttg & 0x7F, state->edacs_tuned_lcn);
fprintf (stderr, " Site [%02llX][%03lld] Group [%05d] Source [%08d] LCN[%02d] ",
state->edacs_site_id, state->edacs_site_id, state->lasttg, state->lastsrc, state->edacs_tuned_lcn);
fprintf (stderr, "%s", KNRM);
}
//load all initial bits before voice into raw_bits array for analysis/handling
for (i = 0; i < 64+16+64; i++)
raw_bits[i] = getDibit (opts, state);
//Note: the initial 144-bits seem to be provisioned differently depending on system type
initial = (unsigned long long int)ConvertBitIntoBytes(&raw_bits[0], 64);
lid = (uint16_t)ConvertBitIntoBytes(&raw_bits[64], 16);
secondary = (unsigned long long int)ConvertBitIntoBytes(&raw_bits[80], 64);
for (i = 0; i < 64; i++)
{
dibit = getDibit (opts, state);
init[i] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
//iNitial 64 bits
if (opts->payload == 1)
{
fprintf (stderr, "\n N64: %016llX", initial);
fprintf (stderr, "\n LID: %04X", lid);
fprintf (stderr, " %016llX", secondary);
k = 0;
fprintf (stderr, "\n N64: ");
for(i = 0; i < 8; i++)
{
initbyte[i] = 0;
for (j = 0; j < 8; j++)
{
initbyte[i] = initbyte[i] << 1;
initbyte[i] = initbyte[i] | init[k];
k++;
}
fprintf (stderr, "%02X", initbyte[i]);
if (i == 3) fprintf (stderr, "-");
}
fprintf (stderr, "\n");
}
// lid
for (i = 0; i < 16; i++)
{
dibit = getDibit (opts, state);
lid[i] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
for (i = 0; i < 64; i++)
{
dibit = getDibit (opts, state);
lid[i+16] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
//load lid (bits) into lidbyte
if (opts->payload == 1)
{
k = 0;
fprintf (stderr, " LID: ");
for(i = 0; i < 10; i++)
{
lidbyte[i] = 0;
for (j = 0; j < 8; j++)
{
lidbyte[i] = lidbyte[i] << 1;
lidbyte[i] = lidbyte[i] | lid[k];
k++;
}
fprintf (stderr, "%02X", lidbyte[i]);
if (i == 3 || i == 7) fprintf (stderr, "-");
}
// fprintf (stderr, "\n");
}
// imbe frames 1,2 first half
w = pW;
x = pX;
for (i = 0; i < 11; i++)
{
for (j = 0; j < 6; j++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[144+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[150+j+(i*12)] = dibit;
}
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+282] = dibit;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 4; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+288] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
// spacer bits
dibit = getDibit (opts, state);
spacer_bit[0] = dibit;
raw_bits[292] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
dibit = getDibit (opts, state);
spacer_bit[1] = dibit;
raw_bits[293] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
fprintf (stderr," ");
#endif
// imbe frames 1,2 second half
for (j = 0; j < 2; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+294] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
for (i = 0; i < 3; i++)
{
for (j = 0; j < 6; j++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[296+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[302+j+(i*12)] = dibit;
}
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+338] = dibit;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+343] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
for (i = 0; i < 7; i++)
{
for (j = 0; j < 6; j++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[348+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[354+j+(i*12)] = dibit;
}
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+438] = dibit;
}
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+443] = dibit;
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
// spacer bits
dibit = getDibit (opts, state);
spacer_bit[2] = dibit;
raw_bits[448] = dibit;
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
dibit = getDibit (opts, state);
spacer_bit[3] = dibit;
raw_bits[449] = dibit;
//resume raw_bits at +6 current value to round out payload bytes
//easier to visualize patterns
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
fprintf (stderr," ");
#endif
for (i = 0; i < 16; i++)
raw_bits[i+450+6] = getDibit (opts, state);
bf = (uint16_t)ConvertBitIntoBytes(&raw_bits[456], 16);
if (opts->payload == 1)
fprintf (stderr, "\n BF: %04X ", bf);
{
dibit = getDibit (opts, state); //HERE
init[i] = dibit; //recycle
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
if (opts->payload == 1)
{
k = 0;
fprintf (stderr, "\n 16B: ");
for(i = 0; i < 2; i++)
{
initbyte[i] = 0;
for (j = 0; j < 8; j++)
{
initbyte[i] = initbyte[i] << 1;
initbyte[i] = initbyte[i] | init[k];
k++;
}
fprintf (stderr, "%02X", initbyte[i]);
}
// fprintf (stderr, "\n");
}
// imbe frames 3,4 first half
w = pW;
x = pX;
for (i = 0; i < 11; i++)
{
for (j = 0; j < 6; j++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[6+466+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[6+472+j+(i*12)] = dibit;
}
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+604+6] = dibit;
}
#ifdef PROVOICE_DUMP
fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 4; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[i+610+6] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
fprintf (stderr," ");
#endif
// spacer bits
dibit = getDibit (opts, state);
spacer_bit[4];
raw_bits[614+2] = dibit;
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
dibit = getDibit (opts, state);
spacer_bit[5];
raw_bits[615+2] = dibit;
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
//fprintf (stderr,"_");
#endif
// imbe frames 3,4 second half
for (j = 0; j < 2; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+616+6] = dibit;
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[6+618+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[6+624+j+(i*12)] = dibit;
}
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
for (i = 0; i < 3; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+660+6] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+665+6] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr," ");
#endif
for (i = 0; i < 7; i++)
{
for (j = 0; j < 6; j++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[6+670+j+(i*12)] = dibit;
}
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[6+676+j+(i*12)] = dibit;
}
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
raw_bits[j+760+6] = dibit;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
raw_bits[j+765+6] = dibit;
}
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
//fprintf (stderr," ");
#endif
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
// spacer bits
dibit = getDibit (opts, state);
spacer_bit[6] = dibit;
raw_bits[782] = dibit;
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
#endif
dibit = getDibit (opts, state);
spacer_bit[7] = dibit;
raw_bits[783] = dibit;
#ifdef PVDEBUG
spacer = (uint8_t)ConvertBitIntoBytes(&spacer_bit[0], 8);
if (opts->payload == 1)
fprintf (stderr, "\n SP: %X", spacer);
//convert raw bits into raw bytes for payload analysis
for (j = 0; j < 98; j++)
{
raw_bytes[j] = (uint8_t)ConvertBitIntoBytes(&raw_bits[(j*8)], 8);
}
//payload on all raw bytes for analysis...its a lot of 'em
if (opts->payload == 1) //find better thingy later or change this
// if (opcode != 0x3333)
{
fprintf (stderr, "%s", KCYN);
fprintf (stderr, "\n pV Payload Dump: \n ");
for (j = 0; j < 98; j++)
{
fprintf (stderr, "[%02X]", raw_bytes[j]);
if (j == 17 || j == 35 || j == 53 || j == 71 || j == 89)
{
fprintf (stderr, "\n ");
}
}
fprintf (stderr, "%s", KNRM);
}
#ifdef PROVOICE_DUMP
//fprintf (stderr,"%i", dibit);
//fprintf (stderr," ");
#endif
//line break at end of frame
fprintf (stderr,"\n");
if (opts->errorbars == 1)
{
fprintf (stderr,"\n");
}
}

Binary file not shown.

Binary file not shown.

BIN
tone8.wav

Binary file not shown.

View File

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