95 Commits

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

1
.gitignore vendored
View File

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

View File

@@ -1,22 +1,15 @@
#Ubuntu 20.04 uses 3.16.3 #Ubuntu 20.04 uses 3.16.3
#Ubuntu 22.04 uses 3.22.1 #Ubuntu 22.04 uses 3.22.1
#Arch currently on 3.26.3 #Arch currently on 3.26.3
#Cygwin currently using 3.23.2 (or newer) #Cygwin currently using 3.23.2 (or newer)
cmake_minimum_required(VERSION 3.10.2) cmake_minimum_required(VERSION 3.10.2)
project(dsd-fme-zdev) project(dsd-fme)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
#Set curses to ncurses, and wide true for ascii #Set curses to ncurses, and wide true for ascii
set(CURSES_NEED_NCURSES TRUE) set(CURSES_NEED_NCURSES TRUE)
set(CURSES_NEED_WIDE TRUE) set(CURSES_NEED_WIDE TRUE)
#use cmake option -DAERO=ON to enable Aero Builds (OSS support and specific tweaks)
option(AERO
"Build for Aero Environments (Cygwin)" OFF)
if (AERO)
add_definitions(-DAERO_BUILD)
endif ()
#use cmake option -DCOLORS=OFF to disable color output #use cmake option -DCOLORS=OFF to disable color output
option(COLORS option(COLORS
"Build with Colors Enabled" ON) "Build with Colors Enabled" ON)
@@ -77,24 +70,24 @@ list(APPEND SRCS "${CMAKE_CURRENT_BINARY_DIR}/git_ver.c")
include_directories("${PROJECT_SOURCE_DIR}/include") include_directories("${PROJECT_SOURCE_DIR}/include")
ADD_EXECUTABLE(dsd-fme-zdev ${SRCS} ${HEADERS}) ADD_EXECUTABLE(dsd-fme ${SRCS} ${HEADERS})
TARGET_LINK_LIBRARIES(dsd-fme-zdev ${LIBS}) TARGET_LINK_LIBRARIES(dsd-fme ${LIBS})
include(GNUInstallDirs) include(GNUInstallDirs)
install(TARGETS dsd-fme-zdev DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS dsd-fme DESTINATION ${CMAKE_INSTALL_BINDIR})
# man page # man page
find_program(HELP2MAN_FOUND help2man) find_program(HELP2MAN_FOUND help2man)
if (HELP2MAN_FOUND) if (HELP2MAN_FOUND)
add_custom_command(TARGET dsd-fme-zdev POST_BUILD add_custom_command(TARGET dsd-fme POST_BUILD
COMMAND help2man COMMAND help2man
ARGS -n "Digital Speech Decoder" ARGS -n "Digital Speech Decoder"
--version-string=${GIT_TAG} --version-string=${GIT_TAG}
-o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-zdev.1 -o ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1
--no-info --no-info
$<TARGET_FILE:dsd-fme-zdev> $<TARGET_FILE:dsd-fme>
) )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme-zdev.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dsd-fme.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif() endif()
# uninstall target # uninstall target

View File

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

View File

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

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

@@ -0,0 +1,67 @@
#! /bin/bash
clear
echo DSD-FME Digital Speech Decoder - Florida Man Edition Auto Installer
echo MBELib is considered a requirement on this build.
echo You must view this notice prior to continuing.
echo The Patent Notice can be found at the site below.
echo https://github.com/lwvmobile/mbelib#readme
echo Please confirm that you have viewed the patent notice by entering y below.
echo
echo y/N
read ANSWER
Y='y'
if [[ $Y == $ANSWER ]]; then
sudo apt update
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev
echo ITPP Manual Build and Install has been temporarily removed from this script due to issues with older versions of Ubuntu.
echo Please check to see that libitpp-dev has successfully been downloaded and installed from the repo.
read -p "Press enter to continue"
#wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
#tar xjf itpp*
#if you can't cd into this folder, double check folder name first
#cd itpp-4.3.1
#mkdir build
#cd build
#cmake ..
#make -j `nproc`
#sudo make install
#sudo ldconfig
#cd ..
#cd ..
git clone https://github.com/lwvmobile/mbelib
cd mbelib
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
cd ..
cd ..
git clone https://github.com/lwvmobile/dsd-fme
cd dsd-fme
sudo cp tone8.wav /usr/share/
sudo cp tone24.wav /usr/share/
sudo cp tone48.wav /usr/share/
sudo chmod 777 /usr/share/tone8.wav
sudo chmod 777 /usr/share/tone24.wav
sudo chmod 777 /usr/share/tone48.wav
mkdir build
cd build
cmake ..
make -j `nproc`
sudo make install
sudo ldconfig
else
echo
echo Sorry, you cannot build DSD-FME without acknowledging the Patent Notice.
fi

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

Binary file not shown.

BIN
dsd-fme2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
dsd-fme3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

181
examples/Example_Usage.md Normal file
View File

@@ -0,0 +1,181 @@
### 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)
```

127
examples/Install_Notes.md Normal file
View File

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

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

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

8
examples/dmr_t3_chan.csv Normal file
View File

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

View File

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

5
examples/group.csv Normal file
View File

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

View File

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

6
examples/multi_key.csv Normal file
View File

@@ -0,0 +1,6 @@
key id or tg id (dec), key number or value (dec) //NXDN, 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

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

5
examples/nxdn_sc_key.csv Normal file
View File

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

40
examples/trunking.sh Normal file
View File

@@ -0,0 +1,40 @@
#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,14 +58,11 @@
#include "p25p1_heuristics.h" #include "p25p1_heuristics.h"
//OSS support
#include <sys/soundcard.h>
#include <pulse/simple.h> //PULSE AUDIO #include <pulse/simple.h> //PULSE AUDIO
#include <pulse/error.h> //PULSE AUDIO #include <pulse/error.h> //PULSE AUDIO
#define SAMPLE_RATE_IN 48000 //48000 #define SAMPLE_RATE_IN 48000 //48000
#define SAMPLE_RATE_OUT 48000 //8000, #define SAMPLE_RATE_OUT 8000 //8000,
#ifdef USE_RTLSDR #ifdef USE_RTLSDR
#include <rtl-sdr.h> #include <rtl-sdr.h>
@@ -204,7 +201,6 @@ typedef struct
int audio_in_type; int audio_in_type;
char audio_out_dev[1024]; char audio_out_dev[1024];
int audio_out_fd; int audio_out_fd;
int audio_out_fdR; //right channel audio for OSS hack
SNDFILE *audio_out_file; SNDFILE *audio_out_file;
SF_INFO *audio_out_file_info; SF_INFO *audio_out_file_info;
@@ -339,12 +335,12 @@ typedef struct
float trunk_hangtime; //hangtime in seconds before tuning back to CC float trunk_hangtime; //hangtime in seconds before tuning back to CC
int scanner_mode; //experimental -- use the channel map as a conventional scanner, quicker tuning, but no CC int scanner_mode; //experimental -- use the channel map as a conventional scanner, quicker tuning, but no CC
//csv import filenames //csv import filenames
char group_in_file[1024]; char group_in_file[1024];
char lcn_in_file[1024]; char lcn_in_file[1024];
char chan_in_file[1024]; char chan_in_file[1024];
char key_in_file[1024]; char key_in_file[1024];
//end import filenames //end import filenames
//reverse mute //reverse mute
@@ -372,9 +368,6 @@ typedef struct
//Trunking - Tune Enc Calls (P25 only on applicable grants with svc opts) //Trunking - Tune Enc Calls (P25 only on applicable grants with svc opts)
uint8_t trunk_tune_enc_calls; uint8_t trunk_tune_enc_calls;
//OSS audio - slot preference
uint8_t slot_preference;
//'DSP' Format Output //'DSP' Format Output
uint8_t use_dsp_output; uint8_t use_dsp_output;
char dsp_out_file[2048]; char dsp_out_file[2048];
@@ -555,7 +548,7 @@ typedef struct
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte] uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
uint8_t cap_plus_csbk_bits[2][12*8*8]; //CSBK Cap+ FL initial and appended block bit storage, by slot uint8_t cap_plus_csbk_bits[2][12*8*8]; //CSBK Cap+ FL initial and appended block bit storage, by slot
uint8_t cap_plus_block_num[2]; //received block number storage -- per timeslot uint8_t cap_plus_block_num[2]; //received block number storage -- per time slot
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure) char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)
@@ -675,7 +668,7 @@ typedef struct
char nxdn_location_category[14]; char nxdn_location_category[14];
uint32_t nxdn_location_sys_code; uint32_t nxdn_location_sys_code;
uint16_t nxdn_location_site_code; uint16_t nxdn_location_site_code;
//channel access information //channel access information
uint8_t nxdn_rcn; uint8_t nxdn_rcn;
uint8_t nxdn_base_freq; uint8_t nxdn_base_freq;
@@ -690,8 +683,8 @@ typedef struct
uint64_t late_entry_mi_fragment[2][7][3]; uint64_t late_entry_mi_fragment[2][7][3];
//dmr manufacturer branding and sub_branding (i.e., Motorola and Con+) //dmr manufacturer branding and sub_branding (i.e., Motorola and Con+)
char dmr_branding[20]; char dmr_branding[99];
char dmr_branding_sub[80]; char dmr_branding_sub[99];
//Remus DMR End Call Alert Beep //Remus DMR End Call Alert Beep
int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag
@@ -827,7 +820,7 @@ void openMbeOutFile (dsd_opts * opts, dsd_state * state);
void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2 void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
void openWavOutFile (dsd_opts * opts, dsd_state * state); void openWavOutFile (dsd_opts * opts, dsd_state * state);
void openWavOutFileL (dsd_opts * opts, dsd_state * state); void openWavOutFileL (dsd_opts * opts, dsd_state * state);
void openWavOutFileR (dsd_opts * opts, dsd_state * state); void openWavOutFileR (dsd_opts * opts, dsd_state * state);
void openWavOutFileRaw (dsd_opts * opts, dsd_state * state); void openWavOutFileRaw (dsd_opts * opts, dsd_state * state);
void openSymbolOutFile (dsd_opts * opts, dsd_state * state); void openSymbolOutFile (dsd_opts * opts, dsd_state * state);
void closeSymbolOutFile (dsd_opts * opts, dsd_state * state); void closeSymbolOutFile (dsd_opts * opts, dsd_state * state);
@@ -897,7 +890,7 @@ void nxdn_deperm_facch2_udch (dsd_opts * opts, dsd_state * state, uint8_t bits[3
//type-d 'idas' deinterleaving/depuncturing functions //type-d 'idas' deinterleaving/depuncturing functions
void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint8_t direction); void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint8_t direction);
void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type); void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type);
//end //end
void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType); void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType);
void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]); void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]);
@@ -964,6 +957,7 @@ uint8_t ComputeCrc5Bit(uint8_t * DMRData);
uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData); uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData);
uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData); uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData);
//new simplified dmr functions //new simplified dmr functions
void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst); void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst);
void dmr_data_sync (dsd_opts * opts, dsd_state * state); void dmr_data_sync (dsd_opts * opts, dsd_state * state);

12
install.sh Normal file
View File

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

16
rebuild.sh Normal file
View File

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

View File

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

View File

@@ -852,11 +852,11 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//check for private activity on LSNs 1-8 //check for private activity on LSNs 1-8
if (fl == 1 || fl == 3) if (fl == 1 || fl == 3)
{ {
if (pdflag) //== 0x80 //testing denny's 0x80 or 0x90 flag discovery if (pdflag == 0x80)
{ {
k = 0; //= 0 k = 0; //= 0
fprintf (stderr, "\n"); fprintf (stderr, "\n");
fprintf (stderr, " Bank One F%X Private or Data Call(s) - ", pdflag); fprintf (stderr, " F%X Private or Data Call - ", pdflag);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
pch[i] = state->cap_plus_csbk_bits[ts][i+48+(group_tally*8)]; pch[i] = state->cap_plus_csbk_bits[ts][i+48+(group_tally*8)];
@@ -876,25 +876,25 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//end private/data call check on LSNs 1-8 //end private/data call check on LSNs 1-8
//check flag for appended private and/or data calls -- flag two still needs work or testing, double checking, etc, disable if issues arise //check flag for appended private and/or data calls -- flag two still needs work or testing, double checking, etc, disable if issues arise
pdflag2 = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][56+(group_tally*8)+(pd_b2*16)], 8); //48 -- had wrong value here (atleast in the one sample with the false positive) pdflag2 = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][48+(group_tally*8)+(pd_b2*16)], 8);
//check for private activity on LSNs 9-16 //check for private activity on LSNs 9-16
if (fl == 1 || fl == 3) if (fl == 1 || fl == 3)
{ {
//then check to see if this byte has a value, should be 0x80, could be other? //then check to see if this byte has a value, should be 0x80, could be other?
//this bytes location shifts depending on level of activity -- see banks above //this bytes location shifts depending on level of activity -- see banks above
if (pdflag2) //== 0x80 //testing denny's 0x80 or 0x90 flag discovery if (pdflag2 == 0x80) //now looking to see if any appended data was added
{ {
k = 0; k = 0;
fprintf (stderr, "\n"); fprintf (stderr, "\n");
fprintf (stderr, " Bank Two F%02X Private or Data Call(s) - ", pdflag2); fprintf (stderr, " F%X Private or Data Call - ", pdflag2);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
pch[i+8] = state->cap_plus_csbk_bits[ts][i+64+(group_tally*8)+(pd_b2*16)]; //56 pch[i+8] = state->cap_plus_csbk_bits[ts][i+56+(group_tally*8)+(pd_b2*16)]; //48
if (pch[i+8] == 1) if (pch[i+8] == 1)
{ {
fprintf (stderr, " LSN %02d:", i+1); fprintf (stderr, " LSN %02d:", i+1);
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][64+(k*16)+(group_tally*8)+(pd_b2*16)], 16); //56 -- had wrong value here (atleast in the one sample with the false positive) private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][64+(k*16)+(group_tally*8)+(pd_b2*16)], 16); //64
fprintf (stderr, " TGT %d;", private_target); fprintf (stderr, " TGT %d;", private_target);
k++; k++;
if (bank_two == 0) bank_two = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display if (bank_two == 0) bank_two = 0xFF; //set all bits on so we can atleast parse all of them below in listing/display
@@ -980,7 +980,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
} }
else if (pch[i] == 1) //private or data channels else if (pch[i] == 1) //private or data channels
{ {
tg = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][(group_tally*8)+(x*16)+56], 16); //don't change this AGAIN!, this is correct! tg = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][(group_tally*8)+(x*16)+56], 16);
if (tg != 0) fprintf (stderr, "%5d; ", tg); if (tg != 0) fprintf (stderr, "%5d; ", tg);
else fprintf (stderr, " P||D; "); else fprintf (stderr, " P||D; ");
//flag as available for tuning if data calls enabled //flag as available for tuning if data calls enabled

View File

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

View File

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

View File

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

View File

@@ -283,8 +283,8 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0; valid = 0;
//disabling again, causing issues with trunking P25 //disabling again, causing issues with trunking
if (state->synctype == 1 && opts->p25_trunk == 1) if (state->synctype == 1 && opts->p25_trunk == 1)
{ {
// Use the P25 heuristics if available // Use the P25 heuristics if available
// valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit); // valid = estimate_symbol(state->rf_mod, &(state->inv_p25_heuristics), state->last_dibit, symbol, &dibit);
@@ -347,7 +347,7 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
valid = 0; valid = 0;
//disabling again, causing issues with trunking P25 //disabling again, causing issues with trunking
if (state->synctype == 0 && opts->p25_trunk == 1) if (state->synctype == 0 && opts->p25_trunk == 1)
{ {
// Use the P25 heuristics if available // 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 * getDateF(void) {
char datename[80]; //32-bit needs this to be 80 char datename[120]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char * curr2; char * curr2;
struct tm * to; struct tm * to;
time_t t; time_t t;

View File

@@ -44,18 +44,6 @@ int pretty_colors()
#include "p25p1_heuristics.h" #include "p25p1_heuristics.h"
#include "pa_devs.h" #include "pa_devs.h"
#ifdef LIMAZULUTWEAKS
char * FM_banner[9] = {
" ",
" ██████╗ ██████╗██████╗ ███╗ ███████╗",
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
" ██║ ██║╚█████╗ ██║ ██║ Lima ███║ ███╔═╝",
" ██║ ██║ ╚═══██╗██║ ██║ Zulu ███║ ██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝ Edition III ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ Windows 32-bit╚═══════╝╚══════╝",
" "
};
#else
char * FM_banner[9] = { char * FM_banner[9] = {
" ", " ",
" ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗",
@@ -66,7 +54,6 @@ char * FM_banner[9] = {
" ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝", " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝",
" " " "
}; };
#endif
int comp (const void *a, const void *b) int comp (const void *a, const void *b)
{ {
@@ -181,7 +168,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->dmr_payload_p = state->dibit_buf + 200; state->dmr_payload_p = state->dibit_buf + 200;
memset (state->dmr_payload_buf, 0, sizeof (int) * 200); memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
//dmr buffer end //dmr buffer end
//close MBE out files //close MBE out files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state); if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
@@ -436,16 +423,11 @@ initOpts (dsd_opts * opts)
opts->p25status = 0; opts->p25status = 0;
opts->p25tg = 0; opts->p25tg = 0;
opts->scoperate = 15; opts->scoperate = 15;
#ifdef AERO_BUILD
sprintf (opts->audio_in_dev, "/dev/dsp");
sprintf (opts->audio_out_dev, "/dev/dsp");
#else
sprintf (opts->audio_in_dev, "pulse"); sprintf (opts->audio_in_dev, "pulse");
sprintf (opts->audio_out_dev, "pulse");
#endif
opts->audio_in_fd = -1; opts->audio_in_fd = -1;
sprintf (opts->audio_out_dev, "pulse");
opts->audio_out_fd = -1; opts->audio_out_fd = -1;
opts->audio_out_fdR = -1;
opts->split = 0; opts->split = 0;
opts->playoffset = 0; opts->playoffset = 0;
@@ -537,10 +519,10 @@ initOpts (dsd_opts * opts)
opts->inverted_dpmr = 0; opts->inverted_dpmr = 0;
opts->dmr_mono = 0; opts->dmr_mono = 0;
opts->dmr_stereo = 1; opts->dmr_stereo = 1;
opts->aggressive_framesync = 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 = 5; opts->audio_in_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
opts->audio_out_type = 5; opts->audio_out_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
opts->lrrp_file_output = 0; opts->lrrp_file_output = 0;
@@ -603,12 +585,6 @@ initOpts (dsd_opts * opts)
opts->dPMR_next_part_of_superframe = 0; 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 //dsp structured file
opts->dsp_out_file[0] = 0; opts->dsp_out_file[0] = 0;
opts->use_dsp_output = 0; opts->use_dsp_output = 0;
@@ -840,7 +816,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 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 //experimental symbol file capture read throttle
state->symbol_throttle = 100; //throttle speed state->symbol_throttle = 0; //throttle speed
state->use_throttle = 0; //only use throttle if set to 1 state->use_throttle = 0; //only use throttle if set to 1
state->p2_scramble_offset = 0; state->p2_scramble_offset = 0;
@@ -850,6 +826,7 @@ initState (dsd_state * state)
state->p25_chan_iden = 0; state->p25_chan_iden = 0;
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
state->p25_chan_tdma[i] = -1; //0, or -1
state->p25_chan_type[i] = 0; state->p25_chan_type[i] = 0;
state->p25_trans_off[i] = 0; state->p25_trans_off[i] = 0;
state->p25_chan_spac[i] = 0; state->p25_chan_spac[i] = 0;
@@ -900,7 +877,7 @@ initState (dsd_state * state)
state->nxdn_location_site_code = 0; state->nxdn_location_site_code = 0;
state->nxdn_location_sys_code = 0; state->nxdn_location_sys_code = 0;
sprintf (state->nxdn_location_category, "%s", " "); sprintf (state->nxdn_location_category, "%s", " ");
//channel access information //channel access information
state->nxdn_rcn = 0; state->nxdn_rcn = 0;
state->nxdn_base_freq = 0; state->nxdn_base_freq = 0;
@@ -909,7 +886,7 @@ initState (dsd_state * state)
//multi-key array //multi-key array
memset (state->rkey_array, 0, sizeof(state->rkey_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 //Remus DMR End Call Alert Beep
state->dmr_end_alert[0] = 0; state->dmr_end_alert[0] = 0;
@@ -922,9 +899,9 @@ initState (dsd_state * state)
//initialize unified dmr pdu 'superframe' //initialize unified dmr pdu 'superframe'
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf)); memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
memset (state->data_header_valid, 0, sizeof(state->data_header_valid)); memset (state->data_header_valid, 0, sizeof(state->data_header_valid));
//initialize cap+ bits and block num storage //initialize cap+ bits and block num storage
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits)); 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_block_num, 0, sizeof(state->cap_plus_block_num));
//init confirmed data individual block crc as invalid //init confirmed data individual block crc as invalid
@@ -970,46 +947,27 @@ usage ()
{ {
printf ("\n"); printf ("\n");
printf ("Usage: dsd-fme-aero [options] Decoder/Trunking Mode\n"); printf ("Usage: dsd-fme [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 [options] -r <files> Read/Play saved mbe data from file(s)\n");
printf (" or: dsd-fme-aero -h Show help\n"); printf (" or: dsd-fme -h Show help\n");
printf ("\n"); printf ("\n");
printf ("Display Options:\n"); printf ("Display Options:\n");
printf (" -N Use NCurses Terminal\n"); printf (" -N Use NCurses Terminal\n");
printf (" dsd-fme-aero -N 2> log.ans \n"); printf (" dsd-fme -N 2> log.ans \n");
printf (" -Z Log MBE/PDU Payloads to console\n"); printf (" -Z Log MBE/PDU Payloads to console\n");
printf ("\n"); printf ("\n");
printf ("Input/Output options:\n"); printf ("Input/Output options:\n");
#ifdef AERO_BUILD printf (" -i <device> Audio input device (default is pulse audio)\n");
printf (" -i <device> Audio input device (default is /dev/dsp)\n"); printf (" - for piped stdin\n");
printf (" pulse for pulse audio (will require pactl running in Cygwin)\n");
#else
printf (" -i <device> Audio input device (default is pulse)\n");
//NOTE: Fix some inputs to /dev/audio if required for linux, or just leave it as the more annoying /dev/dsp -- padsp bug opens multiple input streams...sometimes
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" rtl:dev:freq:gain:ppm:bw:sq:udp for rtl dongle (see below)\n"); printf (" rtl:dev:freq:gain:ppm:bw:sq:udp for rtl dongle (see below)\n");
printf (" tcp for tcp client SDR++/GNURadio Companion/Other (Port 7355)\n"); printf (" tcp for tcp client SDR++/GNURadio Companion/Other (Port 7355)\n");
printf (" tcp:192.168.7.5:7355 for custom address and port \n"); printf (" tcp:192.168.7.5:7355 for custom address and port \n");
printf (" filename.bin for OP25/FME capture bin files\n"); printf (" filename.bin for OP25/FME capture bin files\n");
printf (" filename.wav for 48K/1 wav files (SDR++, GQRX)\n"); printf (" filename.wav for 48K/1 wav files (SDR++, GQRX)\n");
printf (" filename.wav -s 96000 for 96K/1 wav files (DSDPlus)\n"); printf (" filename.wav -s 96000 for 96K/1 wav files (DSDPlus)\n");
#ifdef AERO_BUILD
printf (" (Use single quotes '\\directory\\audio file.wav' when directories/spaces are present)\n");
#else
printf (" (Use single quotes '/directory/audio file.wav' when directories/spaces are present)\n"); printf (" (Use single quotes '/directory/audio file.wav' when directories/spaces are present)\n");
#endif
// 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 (" -s <rate> Sample Rate of wav input files (48000 or 96000) Mono only!\n");
#ifdef AERO_BUILD 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 (" pulse for pulse audio (will require pactl running in Cygwin)\n");
#else
printf (" -o <device> Audio output device (default is pulse)\n");
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" null for no audio output\n");
// printf (" pulse for pulse audio \n");
printf (" -d <dir> Create mbe data files, use this directory (TDMA version is experimental)\n"); printf (" -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 (" -r <files> Read/Play saved mbe data from file(s)\n");
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n"); printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
@@ -1025,7 +983,6 @@ usage ()
printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n"); printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n");
printf (" -V Enable Audio Smoothing on Upsampled 48k/1 or 24k/2 Audio (Capital V)\n"); printf (" -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 (" (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 ("\n");
printf ("RTL-SDR options:\n"); printf ("RTL-SDR options:\n");
printf (" WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>\n"); printf (" WARNING! Old CLI Switch Handling has been depreciated in favor of rtl:<parms>\n");
@@ -1037,10 +994,10 @@ usage ()
printf (" bw <num> RTL-SDR VFO Bandwidth kHz (default = 12)(6, 8, 12, 24) \n"); printf (" bw <num> RTL-SDR VFO Bandwidth kHz (default = 12)(6, 8, 12, 24) \n");
printf (" sq <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)\n"); printf (" 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 (" udp <num> RTL-SDR UDP Remote Port (default = 6020)\n");
printf (" Example: dsd-fme-aero -fp -i rtl:0:851.375M:22:-2:12:0:6021\n"); printf (" Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
printf ("\n"); printf ("\n");
printf ("Decoder options:\n"); printf ("Decoder options:\n");
printf (" -fa Legacy Auto Detection (old methods default)\n"); printf (" -fa Legacy Auto Detection 8k/1 (old methods default)\n");
printf (" -ft XDMA P25 and DMR BS/MS frame types (new 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 (" -fs DMR Stereo BS and MS Simplex\n");
printf (" -f1 Decode only P25 Phase 1\n"); printf (" -f1 Decode only P25 Phase 1\n");
@@ -1097,8 +1054,7 @@ usage ()
printf (" -k <file> Import Key List from csv file.\n"); printf (" -k <file> Import Key List from csv file.\n");
printf (" Only supports NXDN, DMR Basic Privacy and **tera 10-Char (decimal value) only. \n"); printf (" 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 (" (dPMR and **tera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n");
printf (" \n"); printf (" -4 Force DMR Privacy Key over FID and SVC bits \n");
printf (" -4 Force Privacy Key over FID and SVC bits \n");
printf ("\n"); printf ("\n");
printf (" Trunking Options:\n"); printf (" Trunking Options:\n");
printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n"); printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n");
@@ -1121,8 +1077,8 @@ usage ()
printf (" May vary based on system stregnth, etc.\n"); printf (" May vary based on system stregnth, etc.\n");
printf (" -t <secs> Set Trunking or Fast Scan VC/sync loss hangtime in seconds. (default = 1 second) (decimal values permitted) \n"); printf (" -t <secs> Set Trunking or Fast Scan VC/sync loss hangtime in seconds. (default = 1 second) (decimal values permitted) \n");
printf ("\n"); printf ("\n");
printf (" Trunking Example TCP: dsd-fme-aero -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans\n"); printf (" Trunking Example 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-aero -fs -i rtl:0:450M:26:-2:8:0:6020 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\n"); printf (" Trunking Example 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 ("\n"); printf ("\n");
exit (0); exit (0);
} }
@@ -1181,7 +1137,6 @@ if (opts->audio_in_type == 0)
if (opts->audio_out_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); openPulseOutput(opts);
} }
@@ -1302,11 +1257,13 @@ main (int argc, char **argv)
mbe_printVersion (versionstr); mbe_printVersion (versionstr);
fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n"); fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n");
for (short int i = 1; i < 7; i++) { for (short int i = 1; i < 8; i++) {
fprintf (stderr,"%s\n", FM_banner[i]); //fprintf (stderr,"%s%s \n", FM_banner[i], KGRN); //cyan/blue text
fprintf (stderr,"%s\n", FM_banner[i]); //cyan/blue tex
} }
//fprintf (stderr,"%s", KNRM); //change back to normal
fprintf (stderr, "Github Build Version: %s%s \n", GIT_TAG); fprintf (stderr, "Github Build Version: %s \n", GIT_TAG);
fprintf (stderr,"MBElib version %s\n", versionstr); fprintf (stderr,"MBElib version %s\n", versionstr);
initOpts (&opts); initOpts (&opts);
@@ -1316,7 +1273,7 @@ main (int argc, char **argv)
exitflag = 0; exitflag = 0;
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:YK:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1) while ((c = getopt (argc, argv, "haepPqs:t:v: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)
{ {
opterr = 0; opterr = 0;
switch (c) switch (c)
@@ -1328,7 +1285,7 @@ main (int argc, char **argv)
opts.call_alert = 1; opts.call_alert = 1;
break; break;
//Free'd up switches include //Free'd up switches include z
//make sure to put a colon : after each if they need an argument //make sure to put a colon : after each if they need an argument
//or remove colon if no argument required //or remove colon if no argument required
@@ -1337,7 +1294,7 @@ main (int argc, char **argv)
opts.p25_trunk = 0; //turn off trunking mode if user enabled it opts.p25_trunk = 0; //turn off trunking mode if user enabled it
break; break;
case 'k': //NXDN multi-key loader case 'k': //multi-key loader
strncpy(opts.key_in_file, optarg, 1023); strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0'; opts.key_in_file[1023] = '\0';
csvKeyImport(&opts, &state); csvKeyImport(&opts, &state);
@@ -1361,13 +1318,6 @@ main (int argc, char **argv)
opts.use_dsp_output = 1; opts.use_dsp_output = 1;
break; 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 //Enable Audio Smoothing for Upsampled Audio
case '0': case '0':
case 'V': case 'V':
@@ -1569,8 +1519,7 @@ main (int argc, char **argv)
case 'F': case 'F':
opts.aggressive_framesync = 0; opts.aggressive_framesync = 0;
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
//fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n"); fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Pass/Fail\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 DMR RAS/CRC CSBK/DATA Pass/Fail\n");
fprintf (stderr, "Relax NXDN SACCH/FACCH/CAC/F2U CRC Pass/Fail\n"); fprintf (stderr, "Relax NXDN SACCH/FACCH/CAC/F2U CRC Pass/Fail\n");
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
@@ -1597,7 +1546,7 @@ main (int argc, char **argv)
// fprintf (stderr,"Writing mbe data temporarily disabled!\n"); // fprintf (stderr,"Writing mbe data temporarily disabled!\n");
break; break;
case 'c': case 'c': //now is symbol capture bin output like FME Lite
strncpy(opts.symbol_out_file, optarg, 1023); strncpy(opts.symbol_out_file, optarg, 1023);
opts.symbol_out_file[1023] = '\0'; opts.symbol_out_file[1023] = '\0';
fprintf (stderr,"Writing + Appending symbol capture to file %s\n", opts.symbol_out_file); fprintf (stderr,"Writing + Appending symbol capture to file %s\n", opts.symbol_out_file);
@@ -1648,12 +1597,12 @@ main (int argc, char **argv)
opts.frame_dpmr = 0; opts.frame_dpmr = 0;
opts.frame_provoice = 0; opts.frame_provoice = 0;
opts.frame_ysf = 0; opts.frame_ysf = 0;
opts.pulse_digi_rate_out = 48000; // /dev/dsp does need this set to 48000 to properly process the upsampling opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1; opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 1; //switching in 'stereo' for 'mono' opts.dmr_stereo = 0;
opts.dmr_mono = 0; opts.dmr_mono = 1;
state.dmr_stereo = 0; state.dmr_stereo = 0;
//opts.setmod_bw = 7000; // opts.setmod_bw = 7000;
sprintf (opts.output_name, "Legacy Auto"); sprintf (opts.output_name, "Legacy Auto");
} }
else if (optarg[0] == 'd') else if (optarg[0] == 'd')
@@ -1857,7 +1806,6 @@ main (int argc, char **argv)
opts.pulse_digi_rate_out = 24000; opts.pulse_digi_rate_out = 24000;
opts.pulse_digi_out_channels = 2; opts.pulse_digi_out_channels = 2;
sprintf (opts.output_name, "DMR Stereo"); sprintf (opts.output_name, "DMR Stereo");
fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n"); fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n");
} }
else if (optarg[0] == 't') else if (optarg[0] == 't')
@@ -1936,8 +1884,7 @@ main (int argc, char **argv)
// opts.setmod_bw = 7000; // opts.setmod_bw = 7000;
sprintf (opts.output_name, "DMR Mono"); sprintf (opts.output_name, "DMR Mono");
fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n"); fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo '-fs' or XDMA '-ft' is highly encouraged.\n"); fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo or XDMA is highly encouraged.\n");
} }
else if (optarg[0] == 'm') else if (optarg[0] == 'm')
{ {
@@ -2147,19 +2094,12 @@ main (int argc, char **argv)
{ {
opts.audio_in_type = 8; opts.audio_in_type = 8;
state.audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing 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 else
{ {
#ifdef AERO_BUILD
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
opts.audio_in_type = 5;
#else
sprintf (opts.audio_in_dev, "%s", "pulse");
fprintf (stderr, "TCP Connection Failure - Using %s Audio Input.\n", opts.audio_in_dev);
opts.audio_in_type = 0; opts.audio_in_type = 0;
#endif fprintf (stderr, "TCP Connection Failure - Using Pulse Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "pulse");
} }
} }
@@ -2239,149 +2179,63 @@ main (int argc, char **argv)
rtl_ok = 1; rtl_ok = 1;
#endif #endif
#ifdef AERO_BUILD
if (rtl_ok == 0) //not set, means rtl support isn't compiled/available if (rtl_ok == 0) //not set, means rtl support isn't compiled/available
{ {
fprintf (stderr, "RTL Support not enabled/compiled, falling back to OSS /dev/dsp Audio Input.\n"); fprintf (stderr, "RTL Support not enabled/compiled, falling back to Pulse Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
opts.audio_in_type = 5;
}
#else
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 Audio Input.\n");
sprintf (opts.audio_in_dev, "%s", "pulse"); sprintf (opts.audio_in_dev, "%s", "pulse");
opts.audio_in_type = 0; opts.audio_in_type = 0;
} }
#endif
} }
//doesn't work correctly, so just going to reroute to /dev/dsp instead //still need to work out why I can't use this
// if((strncmp(opts.audio_in_dev, "udp", 3) == 0)) //udp socket input from SDR++, GQRX, and others //issues with samples received, may be using UDP DGRAMS incorrectly, incorrect procedure?
// { if((strncmp(opts.audio_in_dev, "udp", 3) == 0)) //udp socket input from SDR++, GQRX, and others
// 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;
// }
int fmt;
int speed = 48000;
//NOTE: Might can use this code in an ifdef to be able to use /dev/audio under padsp in Linux
if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
{ {
sprintf (opts.audio_in_dev, "%s", "/dev/dsp"); //also still needs err handling
fprintf (stderr, "Switching to /dev/dsp.\n"); opts.udp_sockfd = UDPBind(opts.udp_hostname, opts.udp_portno);
} opts.audio_in_type = 6;
if((strncmp(opts.audio_in_dev, "pa", 2) == 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)) if((strncmp(opts.audio_in_dev, "/dev/dsp", 8) == 0))
{ {
fprintf (stderr, "OSS Input %s.\n", opts.audio_in_dev); sprintf (opts.audio_in_dev, "%s", "pulse");
opts.audio_in_fd = open (opts.audio_in_dev, O_RDWR); fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
if (opts.audio_in_fd == -1) opts.audio_in_type = 0;
{
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)) if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
{ {
sprintf (opts.audio_out_dev, "%s", "/dev/dsp"); sprintf (opts.audio_in_dev, "%s", "pulse");
fprintf (stderr, "Switching to /dev/dsp.\n"); fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
} opts.audio_in_type = 0;
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)) if((strncmp(opts.audio_out_dev, "/dev/dsp", 8) == 0))
{ {
fprintf (stderr, "OSS Output %s.\n", opts.audio_out_dev); sprintf (opts.audio_out_dev, "%s", "pulse");
opts.audio_out_fd = open (opts.audio_out_dev, O_RDWR); //O_WRONLY fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
opts.audio_out_fdR = open (opts.audio_out_dev, O_RDWR); opts.audio_out_type = 0;
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) if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0))
{ {
fprintf (stderr, "Error, couldn't open #2 %s\n", opts.audio_out_dev); sprintf (opts.audio_out_dev, "%s", "pulse");
opts.audio_out = 0; fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
exit(1); opts.audio_out_type = 0;
} }
fmt = 0;
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_RESET) < 0) if((strncmp(opts.audio_out_dev, "pa", 2) == 0))
{ {
fprintf (stderr, "ioctl reset error \n"); sprintf (opts.audio_out_dev, "%s", "pulse");
} fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
if (ioctl (opts.audio_out_fdR, SNDCTL_DSP_RESET) < 0) opts.audio_out_type = 0;
{ }
fprintf (stderr, "ioctl reset error \n");
} if((strncmp(opts.audio_in_dev, "pa", 2) == 0))
fmt = speed; {
if (ioctl (opts.audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0) sprintf (opts.audio_in_dev, "%s", "pulse");
{ fprintf (stderr, "OSS and PA Handling Disabled; Using Pulse Audio.\n");
fprintf (stderr, "ioctl speed error \n"); opts.audio_out_type = 0;
}
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)) if((strncmp(opts.audio_in_dev, "pulse", 5) == 0))
@@ -2407,15 +2261,14 @@ main (int argc, char **argv)
opts.playoffsetR = 0; opts.playoffsetR = 0;
opts.delay = 0; opts.delay = 0;
if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0) if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
{ {
openWavOutFile (&opts, &state); openWavOutFile (&opts, &state);
} }
opts.pulse_digi_rate_out = 48000; else
opts.pulse_digi_out_channels = 1; {
if (opts.audio_out_type == 0) openPulseOutput(&opts); openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
if (opts.audio_out_type == 5) openAudioOutDevice (&opts, SAMPLE_RATE_OUT); }
} }
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0) else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
{ {
opts.split = 1; opts.split = 1;
@@ -2448,13 +2301,16 @@ main (int argc, char **argv)
if (opts.playfiles == 1) 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 state.aout_gain = 25; //BUGFIX: No audio output when playing back .amb/.imb files
playMbeFiles (&opts, &state, argc, argv); playMbeFiles (&opts, &state, argc, argv);
} }
else else
{ {
liveScanner (&opts, &state); liveScanner (&opts, &state);
} }
cleanupAndExit (&opts, &state); cleanupAndExit (&opts, &state);

View File

@@ -145,9 +145,6 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
uint8_t hash_bits[24]; uint8_t hash_bits[24];
memset (hash_bits, 0, sizeof(hash_bits)); 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++) for (i = 0; i < 88; i++)
{ {
imbe_d[i] = 0; imbe_d[i] = 0;
@@ -303,8 +300,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
if (state->M == 0) if (state->M == 0)
{ {
//see if we need to hash a value larger than 16-bits //see if we need to hash a value larger than 16-bits
hash = state->lasttg & 0xFFFFFF; hash = state->lasttg & 0xFFFFFF;
// fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash); // fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash);
if (hash > 0xFFFF) //if greater than 16-bits if (hash > 0xFFFF) //if greater than 16-bits
{ {
for (int i = 0; i < 24; i++) for (int i = 0; i < 24; i++)
@@ -611,17 +608,6 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
} }
//end reverse mute test //end reverse mute test
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//OSS Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16)
{
opts->audio_out = 0;
preempt = 1;
if (opts->payload == 0)
fprintf (stderr, " *MUTED*");
}
#endif
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
{ {
state->debug_audio_errors += state->errs2; state->debug_audio_errors += state->errs2;
@@ -678,17 +664,6 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
} }
//end reverse mute test //end reverse mute test
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//OSS Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstL == 16)
{
opts->audio_out = 0;
preempt = 1;
if (opts->payload == 0)
fprintf (stderr, " *MUTED*");
}
#endif
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
{ {
state->debug_audio_errorsR += state->errs2R; state->debug_audio_errorsR += state->errs2R;
@@ -743,12 +718,6 @@ 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 //reset audio out flag for next repitition
if (strcmp(mode, "B") == 0) opts->audio_out = 1; if (strcmp(mode, "B") == 0) opts->audio_out = 1;
//restore flag for null output type //restore flag for null output type

View File

@@ -49,19 +49,7 @@ int i = 0;
char versionstr[25]; char versionstr[25];
unsigned long long int call_matrix[33][6]; unsigned long long int call_matrix[33][6];
#ifdef LIMAZULUTWEAKS
char * FM_bannerN[9] = {
" ",
" ██████╗ ██████╗██████╗ ███╗ ███████╗",
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
" ██║ ██║╚█████╗ ██║ ██║ ███║ ███╔═╝",
" ██║ ██║ ╚═══██╗██║ ██║ Lima ███║ ██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝ Zulu ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ Edition III ╚═══════╝╚══════╝",
" ",
" "
};
#else
char * FM_bannerN[9] = { char * FM_bannerN[9] = {
" ", " ",
" ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ ", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ ",
@@ -73,7 +61,7 @@ char * FM_bannerN[9] = {
" ", " ",
" " " "
}; };
#endif
char * SyncTypes[44] = { char * SyncTypes[44] = {
@@ -109,9 +97,9 @@ char * SyncTypes[44] = {
"NXDN", "NXDN",
"YSF", //30 "YSF", //30
"YSF", "YSF",
"DMR ", "DMR ", //DMR MS VOICE
"DMR ", "DMR ", //DMR MS DATA
"DMR ", "DMR ", //DMR RC DATA
"P25P2", "P25P2",
"P25P2", "P25P2",
"EDACS/PV", //37 "EDACS/PV", //37
@@ -137,7 +125,7 @@ char * DMRBusrtTypes[32] = {
"R-S ERR ", "R-S ERR ",
"CRC ERR ", "CRC ERR ",
"NULL ", "NULL ",
"Voice ", "Voice ",
" ", " ",
"INIT ", "INIT ",
"INIT ", "INIT ",
@@ -162,10 +150,9 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
FILE *beep; FILE *beep;
char wav_name[1024] = {0}; char wav_name[1024] = {0};
if (opts->pulse_digi_rate_out == 8000) strncpy(wav_name, "tone8.wav", 1023); 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, "tone48.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, "tone24.wav", 1023); if (opts->pulse_digi_rate_out == 24000) strncpy(wav_name, "/usr/share/tone24.wav", 1023);
if (opts->audio_out_type == 5) strncpy(wav_name, "tone48.wav", 1023);
wav_name[1023] = '\0'; wav_name[1023] = '\0';
struct stat stat_buf; struct stat stat_buf;
if (stat(wav_name, &stat_buf) == 0) if (stat(wav_name, &stat_buf) == 0)
@@ -187,20 +174,17 @@ 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 //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) if (type == 0 && opts->dmr_stereo == 1 && opts->audio_out == 1)
{ {
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL); 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"); //fprintf (stderr, "BEEP 0 24\n");
} }
if (type == 1 && opts->dmr_stereo == 1 && opts->audio_out == 1) if (type == 1 && opts->dmr_stereo == 1 && opts->audio_out == 1)
{ {
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_outR, buf, sizeof(buf), NULL); 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"); //fprintf (stderr, "BEEP 1 24\n");
} }
if (opts->dmr_stereo == 0 && opts->audio_out == 1) if (opts->dmr_stereo == 0 && opts->audio_out == 1)
{ {
if (opts->audio_out_type == 0) pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL); 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"); //fprintf (stderr, "BEEP 0 8\n");
} }
@@ -215,7 +199,7 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
} }
char * getDateN(void) { char * getDateN(void) {
char datename[80]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text char datename[99]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
char * curr2; char * curr2;
struct tm * to; struct tm * to;
time_t t; time_t t;
@@ -390,7 +374,7 @@ void ncursesOpen (dsd_opts * opts, dsd_state * state)
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
initscr(); //Initialize NCURSES screen window initscr(); //Initialize NCURSES screen window
start_color(); start_color();
#ifdef PRETTY_COLORS #ifdef PRETTY_COLORS
init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style 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 init_pair(2, COLOR_RED, COLOR_BLACK); //Red for Terminated Calls
@@ -437,7 +421,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 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; state->payload_keyid = 0;
@@ -863,13 +847,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if(opts->tcp_file_in == NULL) if(opts->tcp_file_in == NULL)
{ {
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL)); fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
if (opts->audio_out_type == 0) sprintf (opts->audio_in_dev, "%s", "pulse");
{ opts->audio_in_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 state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
@@ -999,8 +978,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
} }
} }
if (opts->audio_out_type == 0) opts->audio_in_type = 0; //set after closing to prevent above crash condition opts->audio_in_type = 0; //set after closing to prevent above crash condition
else (opts->audio_in_type = 5);
choicec = 18; //exit choicec = 18; //exit
} }
@@ -1506,7 +1484,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
src = 0; src = 0;
rn = 0; rn = 0;
tgn = 0; tgn = 0;
dcc = -1; dcc = 0;
tg = 0; tg = 0;
tgR = 0; tgR = 0;
rd = 0; rd = 0;
@@ -1696,7 +1674,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 5) //re-open UDP input 'file' 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 //update sync time on cc sync so we don't immediately go CC hunting when exiting the menu
@@ -1714,8 +1692,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN - if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
{ {
timeout(0); // timeout(0);
c = getch(); // c = getch();
} }
//use rtl_udp_tune //use rtl_udp_tune
@@ -2082,20 +2060,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Start Printing Section //Start Printing Section
erase(); erase();
#ifdef AERO_BUILD
if (opts->ncurses_compact == 1) if (opts->ncurses_compact == 1)
{ {
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", GIT_TAG); printw ("| Digital Speech Decoder: Florida Man Edition %s \n", GIT_TAG);
// printw ("| Digital Speech Decoder: Florida Man Edition - zDEV %s \n", "v2.0.0-100-gae58fab Win32");
} }
#else
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - zDEV %s \n", GIT_TAG);
}
#endif
if (opts->ncurses_compact == 0) if (opts->ncurses_compact == 0)
{ {
attron(COLOR_PAIR(6)); attron(COLOR_PAIR(6));
@@ -2104,15 +2073,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("%s", FM_bannerN[i]); printw("%s", FM_bannerN[i]);
if (i == 1) printw (" ESC to Menu"); if (i == 1) printw (" ESC to Menu");
if (i == 2) printw (" 'q' to Quit "); if (i == 2) printw (" 'q' to Quit ");
if (i == 4) printw (" MBElib %s", versionstr); if (i == 5) printw (" MBElib %s", versionstr);
#ifdef AERO_BUILD
if (i == 5) printw (" %s ", "Aero Win32");
if (i == 6) printw (" %s \n", GIT_TAG); //don't have the git dev package on my cygwin32 bit environment and can't get it now (32-bit no longer supported)
// if (i == 6) printw (" v2.0.0-100-gae58fab \n"); //put appropriate version in here later, or find the GIT_TAG package (git_revision) to build in cygwin
#else
if (i == 5) printw (" %s ", "zDEV BUILD");
if (i == 6) printw (" %s \n", GIT_TAG); if (i == 6) printw (" %s \n", GIT_TAG);
#endif
else printw ("\n"); else printw ("\n");
} }
attroff(COLOR_PAIR(6)); //6 attroff(COLOR_PAIR(6)); //6
@@ -2124,10 +2086,6 @@ 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); 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) if (opts->audio_in_type == 4)
{ {
printw ("| Direct Symbol Bin Input: %s \n", opts->audio_in_dev); printw ("| Direct Symbol Bin Input: %s \n", opts->audio_in_dev);
@@ -2162,12 +2120,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->audio_smoothing == 1) printw (" - Smoothing On"); if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n"); 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) if (opts->monitor_input_audio == 1)
{ {
printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n"); printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n");
@@ -2245,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->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->K1 != 0) printw ("| Forcing Key Priority -- tera BP Key: %016llX \n", state->K1);
if (state->K != 0 && state->K1 != 0) printw ("| Warning! Multiple DMR Key Types Loaded! \n"); //warning may not be required if (state->K != 0 && state->K1 != 0) printw ("| Warning! Multiple DMR Key Types Loaded! \n"); //warning may not be required
} }
if (opts->scanner_mode == 1) if (opts->scanner_mode == 1)
{ {
printw ("| Fast Scan Mode Enabled "); printw ("| Fast Scan Mode Enabled ");
if (state->lcn_freq_roll != 0) if (state->lcn_freq_roll != 0)
printw (" - Frequency: [%.06lf] Mhz", (double)state->trunk_lcn_freq[state->lcn_freq_roll-1]/1000000); 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"); printw ("------------------------------------------------------------------------------\n");
attroff(COLOR_PAIR(4)); attroff(COLOR_PAIR(4));
@@ -2546,13 +2498,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//This is the new one //This is the new one
printw ("%s | ", state->call_string[0]); printw ("%s | ", state->call_string[0]);
printw ("%s ", DMRBusrtTypes[state->dmrburstL]); printw ("%s ", DMRBusrtTypes[state->dmrburstL]);
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
//
#endif
printw ("\n"); printw ("\n");
printw ("| V XTRA | "); //10 spaces printw ("| V XTRA | "); //10 spaces
@@ -2644,7 +2589,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Not always correct, or correct at all, depends on context //Not always correct, or correct at all, depends on context
//this is already in the call_string anyways //this is already in the call_string anyways
// if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000 // if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000
// { // {
// attron(COLOR_PAIR(2)); // attron(COLOR_PAIR(2));
@@ -2674,6 +2619,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
if(state->dmrburstL == 16) //only during call if(state->dmrburstL == 16) //only during call
{ {
@@ -2699,7 +2645,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
//LRRP //LRRP
if(state->dmrburstL != 16) //only during data and no trunking if(state->dmrburstL != 16) //only during data and no trunking
{ {
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
printw ("%s", state->dmr_lrrp_gps[0]); printw ("%s", state->dmr_lrrp_gps[0]);
@@ -2748,11 +2694,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//THIS IS THE NEW ONE //THIS IS THE NEW ONE
printw ("%s | ", state->call_string[1]); printw ("%s | ", state->call_string[1]);
printw ("%s ", DMRBusrtTypes[state->dmrburstR]); printw ("%s ", DMRBusrtTypes[state->dmrburstR]);
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && state->dmrburstR == 16 && state->dmrburstL == 16) printw ("*M*");
//
#endif
printw ("\n"); printw ("\n");
printw ("| V XTRA | "); //10 spaces printw ("| V XTRA | "); //10 spaces
@@ -2864,6 +2805,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
if(state->dmrburstR == 16) //only during call if(state->dmrburstR == 16) //only during call
{ {
@@ -2948,7 +2890,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else attroff(COLOR_PAIR(4)); else attroff(COLOR_PAIR(4));
printw ("\n"); printw ("\n");
} }
} // end if not MS } // end if not MS
} //end DMR BS Types } //end DMR BS Types
@@ -3148,151 +3090,149 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
refresh(); refresh();
//keyboard shortcuts - codes same as ascii codes //keyboard shortcuts - codes same as ascii codes
if (c == 27) //esc key, open menu 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 (c == 122) //'z' key, toggle payload to console
{ {
if (opts->payload == 1) opts->payload = 0; if (opts->payload == 1) opts->payload = 0;
else opts->payload = 1; else opts->payload = 1;
} }
if (c == 99) //'c' key, toggle compact mode if (c == 99) //'c' key, toggle compact mode
{ {
if (opts->ncurses_compact == 1) opts->ncurses_compact = 0; if (opts->ncurses_compact == 1) opts->ncurses_compact = 0;
else opts->ncurses_compact = 1; else opts->ncurses_compact = 1;
} }
if (c == 116) //'t' key, toggle trunking if (c == 116) //'t' key, toggle trunking mode
{ {
if (opts->p25_trunk == 1) opts->p25_trunk = 0; if (opts->p25_trunk == 1) opts->p25_trunk = 0;
else opts->p25_trunk = 1; else opts->p25_trunk = 1;
} opts->scanner_mode = 0; //turn off scanner mode
}
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; if (opts->scanner_mode == 1) opts->scanner_mode = 0;
else opts->scanner_mode = 1; else opts->scanner_mode = 1;
opts->p25_trunk = 0; //turn off trunking mode opts->p25_trunk = 0; //turn off trunking mode
} }
if (c == 97) //'a' key, toggle call alert beep if (c == 97) //'a' key, toggle call alert beep
{ {
if (opts->call_alert == 1) opts->call_alert = 0; if (opts->call_alert == 1) opts->call_alert = 0;
else opts->call_alert = 1; else opts->call_alert = 1;
} }
if (c == 104) //'h' key, toggle history if (c == 104) //'h' key, toggle history
{ {
if (opts->ncurses_history == 1) opts->ncurses_history = 0; if (opts->ncurses_history == 1) opts->ncurses_history = 0;
else opts->ncurses_history = 1; else opts->ncurses_history = 1;
} }
if (c == 113) //'q' key, quit if (c == 113) //'q' key, quit
{ {
ncursesClose(); ncursesClose();
cleanupAndExit (opts, state); cleanupAndExit (opts, state);
} }
if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr) if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr)
{ {
if (state->M == 1) state->M = 0; if (state->M == 1) state->M = 0;
else state->M = 1; else state->M = 1;
} }
if (c == 105) //'i' key, toggle signal inversion on inverted types if (c == 105) //'i' key, toggle signal inversion on inverted types
{
//Set all signal for inversion or uninversion
if (opts->inverted_dmr == 0)
{ {
//Set all signal for inversion or uninversion opts->inverted_dmr = 1;
if (opts->inverted_dmr == 0) opts->inverted_dpmr = 1;
{ opts->inverted_x2tdma = 1;
opts->inverted_dmr = 1; opts->inverted_ysf = 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;
}
} }
else
if (c == 109) //'m' key, toggle qpsk/c4fm - everything but phase 2
{ {
if (state->rf_mod == 0) opts->inverted_dmr = 0;
{ opts->inverted_dpmr = 0;
opts->mod_c4fm = 0; opts->inverted_x2tdma = 0;
opts->mod_qpsk = 1; opts->inverted_ysf = 0;
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 (c == 109) //'m' key, toggle qpsk/c4fm - everything but phase 2
{
if (state->rf_mod == 0)
{ {
if (state->rf_mod == 0) opts->mod_c4fm = 0;
{ opts->mod_qpsk = 1;
opts->mod_c4fm = 0; opts->mod_gfsk = 0;
opts->mod_qpsk = 1; state->rf_mod = 1;
opts->mod_gfsk = 0; state->samplesPerSymbol = 10;
state->rf_mod = 1; state->symbolCenter = 4;
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;
}
} }
else
if (c == 82) //'R', save symbol capture bin with date/time string as name {
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)
{
opts->symbol_out = 1; //set flag to 1
openSymbolOutFile (opts, state);
}
}
if (c == 114) //'r' key, stop capturing symbol capture bin file
{
if (opts->symbol_out == 1)
{ {
sprintf (opts->symbol_out_file, "%s %s.bin", getDateN(), getTimeN());
if (opts->symbol_out_file[0] != 0) if (opts->symbol_out_file[0] != 0)
{ {
opts->symbol_out = 1; //set flag to 1 fclose(opts->symbol_out_f);
openSymbolOutFile (opts, state); sprintf (opts->audio_in_dev, "%s", opts->symbol_out_file);
} }
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);
}
opts->symbol_out = 0;
}
}
#ifdef AERO_BUILD
//do nothing
#else
if (c == 32) //'space bar' replay last bin file (rework to do wav files too?) if (c == 32) //'space bar' replay last bin file (rework to do wav files too?)
{ {
struct stat stat_buf; struct stat stat_buf;
@@ -3308,9 +3248,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
SKIPR: ; //do nothing SKIPR: ; //do nothing
} }
#endif
if (c == 80) //'P' key - start per call wav files if (c == 80) //'P' key - start per call wav files
{ {
@@ -3343,10 +3280,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->dmr_stereo_wav = 0; opts->dmr_stereo_wav = 0;
} }
//
#ifdef AERO_BUILD //this might be okay on Aero as well, will need to look into and/or test
//
#else
if (c == 115) //'s' key, stop playing wav or symbol in files if (c == 115) //'s' key, stop playing wav or symbol in files
{ {
if (opts->symbolfile != NULL) if (opts->symbolfile != NULL)
@@ -3362,16 +3296,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
sf_close(opts->audio_in_file); sf_close(opts->audio_in_file);
} }
if (opts->audio_out_type == 0) opts->audio_in_type = 0;
{ openPulseInput(opts);
opts->audio_in_type = 0;
openPulseInput(opts);
}
else opts->audio_in_type = 5;//cleanupAndExit(opts, state);
} }
#endif
//test jumping back to CC on group lockout instead of random frequency to break framesync //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 if (state->lasttg != 0 && opts->frame_provoice != 1 && c == 49) //'1' key, lockout slot 1 or conventional tg from tuning/playback during session
{ {
@@ -3591,9 +3519,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else opts->use_rigctl = 0; else opts->use_rigctl = 0;
} }
//anything with an entry box will need the inputs and outputs stopped first //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 //so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those //needing an entry box, then stop all of those
} //end ncursesPrinter } //end ncursesPrinter

View File

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

View File

@@ -1303,7 +1303,6 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
if (opcode == 0x4 || opcode == 0x0) //INFO 4 if (opcode == 0x4 || opcode == 0x0) //INFO 4
{ {
//clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?) //clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?)
//may not be entirely necessary here in this context
if ( (time(NULL) - state->last_active_time) > 3 ) if ( (time(NULL) - state->last_active_time) > 3 )
{ {
memset (state->active_channel, 0, sizeof(state->active_channel)); memset (state->active_channel, 0, sizeof(state->active_channel));

View File

@@ -475,16 +475,6 @@ void process_4V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
}
#endif
processMbeFrame (opts, state, NULL, ambe_fr1, NULL); processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL); processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL); processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
@@ -636,16 +626,6 @@ void process_2V (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }
#ifdef AERO_BUILD //FUN FACT: OSS stutters only on Cygwin, using padsp in linux, it actually opens two virtual /dev/dsp audio streams for output
//Cygwin OSS Slot Preference Pre-emption shim
if (opts->audio_out_type == 5)
{
//set to 16 for MBE OSS shim to preempt audio
if (state->currentslot == 0) state->dmrburstL = 16;
else state->dmrburstR = 16;
}
#endif
processMbeFrame (opts, state, NULL, ambe_fr1, NULL); processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL); processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
@@ -851,7 +831,7 @@ void processP2 (dsd_opts * opts, dsd_state * state)
p2_dibit_buffer (opts, state); p2_dibit_buffer (opts, state);
//look at our ISCH values and determine location in superframe before running frame scramble //look at our ISCH values and determine location in superframe before running frame scramble
for (framing_counter = 0; framing_counter < 4; framing_counter++) for (framing_counter = 0; framing_counter < 4; framing_counter++)
{ {
//run ISCH in here so we know when to start descramble offset //run ISCH in here so we know when to start descramble offset
process_ISCH (opts, state); process_ISCH (opts, state);
@@ -870,18 +850,6 @@ void processP2 (dsd_opts * opts, dsd_state * state)
//process DUID will run through all collected frames and handle them appropriately //process DUID will run through all collected frames and handle them appropriately
process_P2_DUID (opts, state); process_P2_DUID (opts, state);
state->dmr_stereo = 0; state->dmr_stereo = 0;
state->p2_is_lcch = 0; state->p2_is_lcch = 0;
//bugfix for OSS slot preferred pre-emption on dual voices
//in case or marginal signal or bad decoding and both get stuck on 16, indefinitely muting the non-preferred slot
//BUG: This causes an annoying blink blink in ncurses, just FYI -- find a better workaround
#ifdef AERO_BUILD
if (opts->audio_out_type == 5)
{
//set both to blank value
state->dmrburstL = 17;
state->dmrburstR = 17;
}
#endif
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }

View File

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

BIN
tone24.wav Normal file

Binary file not shown.

BIN
tone48.wav Normal file

Binary file not shown.

BIN
tone8.wav Normal file

Binary file not shown.

4
virtualsink.sh Normal file
View File

@@ -0,0 +1,4 @@
pactl load-module module-null-sink sink_name=virtual_sink sink_properties=device.description=Virtual_Sink
pactl load-module module-null-sink sink_name=virtual_sink2 sink_properties=device.description=Virtual_Sink2