25 Commits
aw_dev ... 2.1b

Author SHA1 Message Date
lwvmobile
6f1cf0a279 Version/Tag Update 2.1b 2023-07-11 19:02:56 -04:00
lwvmobile
5d045b89e4 Fix Random Warnings on #152 2023-07-10 19:19:49 -04:00
lwvmobile
a2c4679632 M17 More Work and Fixes; #152 2023-07-10 19:13:16 -04:00
lwvmobile
986ed27d7d NXDN LZ Tweak on RCCH Disc; #123 2023-07-10 19:02:54 -04:00
lwvmobile
bae6a1545e Fix OSS Input/Output on M17 8K Sample; #152 2023-07-08 23:58:43 -04:00
lwvmobile
5240f00441 M17 Dbuf Temp Bug Fix; Misc; #152 2023-07-08 06:40:36 -04:00
lwvmobile
f7511e0976 Fix Cmake for Codec2 in Cygwin; #152 2023-07-08 06:07:09 -04:00
lwvmobile
bc27344b04 Fix M17 3200bps Voice; Misc M17 Tweaks; #152 2023-07-07 02:15:08 -04:00
lwvmobile
db97eb82a1 M17 Support (Partially Working Now); 2023-07-06 21:04:28 -04:00
lwvmobile
3f1b8ff736 M17 Initial Support (Non-Working State); 2023-07-05 14:27:25 -04:00
lwvmobile
54b9017146 Misc Minor Fixes; 2023-07-05 14:03:22 -04:00
lwvmobile
8ccaf2d261 DMR LE ENC Identifiers Tweak; 2023-07-03 12:31:58 -04:00
lwvmobile
209770175d Fix ysf.c Unused Variables Warnings; 2023-07-01 22:56:15 -04:00
lwvmobile
602079e681 Fix Trellis.c Unused Variables Warnings; 2023-07-01 22:47:36 -04:00
lwvmobile
82267b9ec8 Fix NXDN de-scrambling bug; 2023-07-01 22:40:05 -04:00
lwvmobile
87bf997b6e Add YSF to default decoding class; #143 2023-07-01 18:44:14 -04:00
lwvmobile
0a43d3202d YSF Fix CM Variable; Line Break; #146 2023-07-01 17:32:42 -04:00
lwvmobile
ee04cef6f2 YSF Radio ID Mode; Element Tweaks; #143 2023-07-01 17:32:22 -04:00
lwvmobile
b6fdfe48c1 Fix Line #137 2023-07-01 17:32:12 -04:00
lwvmobile
7a4bd2833f Refine/Fix YSF FICH Element Decode #143 2023-07-01 17:31:42 -04:00
lwvmobile
432ad448ba Fix YSF Full Rate Voice #143 2023-07-01 17:31:27 -04:00
lwvmobile
61be710bb0 Fix Code Tab Alignment #143 2023-07-01 17:30:57 -04:00
lwvmobile
3be8aacf77 WIP: YSF Decoding; #143 2023-07-01 17:30:29 -04:00
lwvmobile
4feb21cf0a Fix Exitflag Variable #136 2023-07-01 17:28:13 -04:00
lwvmobile
7d8162ab99 DMR LE/CAP+/Misc Tweaks; 2023-07-01 17:21:43 -04:00
26 changed files with 2613 additions and 429 deletions

View File

@@ -68,6 +68,7 @@ find_package(ITPP REQUIRED)
find_package(RTLSDR) find_package(RTLSDR)
find_package(Curses REQUIRED) find_package(Curses REQUIRED)
find_package(PulseAudio REQUIRED) find_package(PulseAudio REQUIRED)
find_package(CODEC2)
include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR})
set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY})
@@ -79,6 +80,12 @@ if(RTLSDR_FOUND)
add_definitions(-DUSE_RTLSDR) add_definitions(-DUSE_RTLSDR)
endif(RTLSDR_FOUND) endif(RTLSDR_FOUND)
if(CODEC2_FOUND)
include_directories(SYSTEM ${CODEC2_INCLUDE_DIRS})
list(APPEND LIBS ${CODEC2_LIBRARIES})
add_definitions(-DUSE_CODEC2)
endif(CODEC2_FOUND)
FILE(GLOB SRCS src/*.c src/*.cpp) FILE(GLOB SRCS src/*.c src/*.cpp)
FILE(GLOB HEADERS include/*.h include/*.hpp) FILE(GLOB HEADERS include/*.h include/*.hpp)

View File

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

31
cmake/FindCODEC2.cmake Normal file
View File

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

View File

@@ -13,7 +13,7 @@ Y='y'
if [[ $Y == $ANSWER ]]; then if [[ $Y == $ANSWER ]]; then
sudo apt update sudo apt update
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev libcodec2-dev
echo ITPP Manual Build and Install has been temporarily removed from this script due to issues with older versions of Ubuntu. echo ITPP Manual Build and Install has been temporarily removed from this script due to issues with older versions of Ubuntu.
echo Please check to see that libitpp-dev has successfully been downloaded and installed from the repo. echo Please check to see that libitpp-dev has successfully been downloaded and installed from the repo.

View File

@@ -3,7 +3,7 @@
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25. To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed. `dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25. 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) -ft XDMA decoder class (P25p1 and p2, YSF, and DMR Stereo)
-fs DMR Stereo, also may need to use -xr if inverted DMR -fs DMR Stereo, also may need to use -xr if inverted DMR
-fa Legacy Auto (not recommended) -fa Legacy Auto (not recommended)
-fi NXDN48 -fi NXDN48
@@ -14,6 +14,7 @@
-f1 P25P1 -f1 P25P1
-f2 P25P2 (may need to specify wacn/sys/nac manually) -f2 P25P2 (may need to specify wacn/sys/nac manually)
-fx X2-TDMA -fx X2-TDMA
-fy YSF
``` ```
## Conventional Frequency "Fast Scanner" ## Conventional Frequency "Fast Scanner"

View File

@@ -28,20 +28,20 @@ Debian/Mint/Ubuntu/Pi
``` ```
sudo apt update sudo apt update
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev libcodec2-dev
``` ```
Fedora 36/37 -- from https://github.com/lwvmobile/dsd-fme/issues/99 Fedora (Recent Releases) -- from https://github.com/lwvmobile/dsd-fme/issues/99
``` ```
sudo dnf install libsndfile-devel fftw-devel lapack-devel rtl-sdr-devel pulseaudio-libs-devel libusb-devel cmake git ncurses ncurses-devel gcc wget pavucontrol gcc-c++ sudo dnf install libsndfile-devel fftw-devel lapack-devel rtl-sdr-devel pulseaudio-libs-devel libusb-devel cmake git ncurses ncurses-devel gcc wget pavucontrol gcc-c++ codec2-devel
``` ```
## Headless Ubuntu Server/Pi ## Headless Ubuntu Server/Pi
If running headless, swap out pavucontrol for pulsemixer, and also install pulseaudio as well. Attempting to install pavucontrol in a headless environment may attempt to install a minimal desktop environment. Note: Default behavior of pulseaudio in a headless environment may be to be muted, so check by opening pulsemixer and unmuting and routing audio appropriately. If running headless, swap out pavucontrol for pulsemixer, and also install pulseaudio as well. Attempting to install pavucontrol in a headless environment may attempt to install a minimal desktop environment. Note: Default behavior of pulseaudio in a headless environment may be to be muted, so check by opening pulsemixer and unmuting and routing audio appropriately.
``` ```
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev pulsemixer pulseaudio sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev pulsemixer pulseaudio libcodec2-dev
``` ```
### Build and Install ITPP - ONLY IF NOT IN REPO!! ### Build and Install ITPP - ONLY IF NOT IN REPO!!

View File

@@ -74,7 +74,11 @@
#include <locale.h> #include <locale.h>
#include <ncurses.h> #include <ncurses.h>
static volatile int exitflag; #ifdef USE_CODEC2
#include <codec2/codec2.h>
#endif
extern volatile uint8_t exitflag; //fix for issue #136
//group csv import struct //group csv import struct
typedef struct typedef struct
@@ -309,6 +313,9 @@ typedef struct
int inverted_ysf; int inverted_ysf;
short int aggressive_framesync; short int aggressive_framesync;
int frame_m17;
int inverted_m17;
FILE *symbolfile; FILE *symbolfile;
int call_alert; int call_alert;
@@ -706,14 +713,62 @@ typedef struct
//Upsampled Audio Smoothing //Upsampled Audio Smoothing
uint8_t audio_smoothing; uint8_t audio_smoothing;
//YSF Fusion Call Strings and Info
uint8_t ysf_dt; //data type -- VD1, VD2, Full Rate, etc.
uint8_t ysf_fi; //frame information -- HC, CC, TC
uint8_t ysf_cm; //group or private call
char ysf_tgt[11];
char ysf_src[11];
char ysf_upl[11];
char ysf_dnl[11];
char ysf_rm1[6];
char ysf_rm2[6];
char ysf_rm3[6];
char ysf_rm4[6];
char ysf_txt[21][21]; //text storage blocks
//M17 Storage
uint8_t m17_lsf[360];
uint8_t m17_str_dt; //stream contents
unsigned long long int m17_dst;
unsigned long long int m17_src;
char m17_dst_csd[20];
char m17_src_csd[20];
char m17_src_str[50];
char m17_dst_str[50];
uint8_t m17_meta[14]; //packed meta
uint8_t m17_enc; //enc type
uint8_t m17_enc_st; //scrambler or data subtye
//Codec2
#ifdef USE_CODEC2
struct CODEC2 *codec2_3200; //M17 fullrate
struct CODEC2 *codec2_1600; //M17 halfrate
#endif
} dsd_state; } dsd_state;
/* /*
* Frame sync patterns * Frame sync patterns
*/ */
#define FUSION_SYNC "31111311313113131131" //HA! //The inverse of LSF also seems to be Stream Frame Type, only going to work on Stream mode for now
#define INV_FUSION_SYNC "13333133131331313313" //HA! #define M17_LSF "11113313"
#define M17_STR "33331131"
//alternating with last symbol opposite of first symbol of LSF
#define M17_PRE "31313131"
#define M17_PIV "13131313"
#define M17_PRE_LSF "3131313133331131" //Preamble + LSF
#define M17_PIV_LSF "1313131311113313" //Preamble + LSF
// #define M17_BRT "31331111"
// #define M17_PKT "13113333"
#define FUSION_SYNC "31111311313113131131"
#define INV_FUSION_SYNC "13333133131331313313"
#define INV_P25P1_SYNC "333331331133111131311111" #define INV_P25P1_SYNC "333331331133111131311111"
#define P25P1_SYNC "111113113311333313133333" #define P25P1_SYNC "111113113311333313133333"
@@ -879,12 +934,15 @@ void processX2TDMAdata (dsd_opts * opts, dsd_state * state);
void processX2TDMAvoice (dsd_opts * opts, dsd_state * state); void processX2TDMAvoice (dsd_opts * opts, dsd_state * state);
void processDSTAR_HD (dsd_opts * opts, dsd_state * state); void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
void processYSF(dsd_opts * opts, dsd_state * state); //YSF void processYSF(dsd_opts * opts, dsd_state * state); //YSF
void processM17STR(dsd_opts * opts, dsd_state * state); //M17 (STR)
void processM17LSF(dsd_opts * opts, dsd_state * state); //M17 (LSF)
void processP2(dsd_opts * opts, dsd_state * state); //P2 void processP2(dsd_opts * opts, dsd_state * state); //P2
void processTSBK(dsd_opts * opts, dsd_state * state); //P25 Trunking Single Block void processTSBK(dsd_opts * opts, dsd_state * state); //P25 Trunking Single Block
void processMPDU(dsd_opts * opts, dsd_state * state); //P25 Multi Block PDU (SAP 0x61 FMT 0x15 or 0x17 for Trunking Blocks) void processMPDU(dsd_opts * opts, dsd_state * state); //P25 Multi Block PDU (SAP 0x61 FMT 0x15 or 0x17 for Trunking Blocks)
short dmr_filter(short sample); short dmr_filter(short sample);
short nxdn_filter(short sample); short nxdn_filter(short sample);
short dpmr_filter(short sample); short dpmr_filter(short sample);
short m17_filter(short sample);
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr); int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr);
uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength); uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);

View File

@@ -258,7 +258,6 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
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;
} }

View File

@@ -272,6 +272,12 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
uint8_t key = (sbrc_hex >> 3) & 0xFF; uint8_t key = (sbrc_hex >> 3) & 0xFF;
uint8_t txi_delay = (sbrc_hex >> 3) & 0x1F; //middle five are the 'delay' value on a TXI system uint8_t txi_delay = (sbrc_hex >> 3) & 0x1F; //middle five are the 'delay' value on a TXI system
//Note: AES-256 Key 1 will pass a CRC3 due to its bit arrangement vs the CRC poly 1101
// if (irr_err == 0 && sbrc_hex = 0xD) crc3_okay = 0; //SB: 00000001101
//NOTE: on above, I belive that we need to check by opcode as well, as a CRC3 can have multiple collisions
//so we need to exclude op/alg 0 and 3 from the check (does algID 0x03/0x23 even exist?)
if (opts->dmr_le == 1) //this will now require a user to switch it on or off until more testing/figuring can be done if (opts->dmr_le == 1) //this will now require a user to switch it on or off until more testing/figuring can be done
{ {
if (irr_err != 0) fprintf (stderr, "\n%s SLOT %d SB/RC (FEC ERR) %d %s \n", KRED, slot, irr_err, KNRM); if (irr_err != 0) fprintf (stderr, "\n%s SLOT %d SB/RC (FEC ERR) %d %s \n", KRED, slot, irr_err, KNRM);
@@ -289,8 +295,8 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
//do something with the reverse channel information //do something with the reverse channel information
} }
//if the call is interruptable (TXI) and the crc3 is okay //if the call is interruptable (TXI) and the crc3 is okay and TXI Opcode
else if (crc3_okay == 1) else if (crc3_okay == 1 && (sbrc_opcode == 0 || sbrc_opcode == 3) )
{ {
//opcodes -- 0 (NULL), BR Delay (3) //opcodes -- 0 (NULL), BR Delay (3)
fprintf (stderr, "\n"); fprintf (stderr, "\n");
@@ -308,7 +314,7 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
} }
else //all that should be left in this field is the potential ENC identifiers else if (sbrc_opcode != 0 || sbrc_opcode != 3) //all that should be left in this field is the potential ENC identifiers
{ {
if (slot == 0) //may not need the state->errs anymore //&& state->errs < 3 if (slot == 0) //may not need the state->errs anymore //&& state->errs < 3

View File

@@ -637,6 +637,47 @@ openAudioInDevice (dsd_opts * opts)
} }
} }
//test .rrc files with hardset wav file settings
else if (strncmp(extension, ".rrc", 3) == 0)
{
//debug
fprintf (stderr, "Opening M17 .rrc headless wav file\n");
opts->audio_in_type = 2;
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->samplerate = 48000;
opts->audio_in_file_info->channels = 1;
opts->audio_in_file_info->seekable = 0;
opts->audio_in_file_info->format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
if(opts->audio_in_file == NULL)
{
fprintf(stderr, "Error, couldn't open %s with libsndfile: %s\n", opts->audio_in_dev, sf_strerror(NULL));
exit(1);
}
}
//TODO: test .sym files as symbol capture .bin files
else if (strncmp(extension, ".sym", 3) == 0)
{
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0)
{
fprintf (stderr,"Error, couldn't open bin file %s\n", opts->audio_in_dev);
exit(1);
}
if (S_ISREG(stat_buf.st_mode))
{
opts->symbolfile = fopen(opts->audio_in_dev, "r");
opts->audio_in_type = 4; //symbol capture bin files
}
else
{
opts->audio_in_type = 0;
}
}
else if (strncmp(extension, ".bin", 3) == 0) else if (strncmp(extension, ".bin", 3) == 0)
{ {
struct stat stat_buf; struct stat stat_buf;

View File

@@ -265,18 +265,21 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) || else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) ||
(state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) || (state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) ||
(state->synctype == 17) || (state->synctype == 29) || (state->synctype == 36) ) (state->synctype == 17) || (state->synctype == 29) || (state->synctype == 31) ||
(state->synctype == 36) || (state->synctype == 99) )
{ {
// 1 -P25p1 // 1 -P25p1
// 3 -X2-TDMA (inverted signal voice frame) // 3 -X2-TDMA (inverted signal voice frame)
// 5 -X2-TDMA (inverted signal data frame) // 5 -X2-TDMA (inverted signal data frame)
// 9 -NXDN (inverted voice frame) // 9 -M17 LSR
// 11 -DMR (inverted signal voice frame) // 11 -DMR (inverted signal voice frame)
// 13 -DMR (inverted signal data frame) // 13 -DMR (inverted signal data frame)
// 17 -NXDN (inverted data frame) // 17 -M17 STR
// 29 -NXDN (inverted FSW) // 29 -NXDN (inverted FSW)
// 31 -YSF
// 36 -P25p2 // 36 -P25p2
// 99 -M17 Preamble
int valid; int valid;
int dibit; int dibit;
@@ -335,12 +338,14 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
// 0 +P25p1 // 0 +P25p1
// 2 +X2-TDMA (non inverted signal data frame) // 2 +X2-TDMA (non inverted signal data frame)
// 4 +X2-TDMA (non inverted signal voice frame) // 4 +X2-TDMA (non inverted signal voice frame)
// 8 +NXDN (non inverted voice frame) // 8 +M17 LSF
// 10 +DMR (non inverted signal data frame) // 10 +DMR (non inverted signal data frame)
// 12 +DMR (non inverted signal voice frame) // 12 +DMR (non inverted signal voice frame)
// 16 +NXDN (non inverted data frame) // 16 +M17 STR
// 28 +NXND (FSW) // 28 +NXND (FSW)
// 30 +YSF
// 35 +p25p2 // 35 +p25p2
// 98 +M17 Preamble
int valid; int valid;
int dibit; int dibit;

View File

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

View File

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

View File

@@ -114,16 +114,16 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
* 5 = -X2-TDMA (inverted signal data frame) * 5 = -X2-TDMA (inverted signal data frame)
* 6 = +D-STAR * 6 = +D-STAR
* 7 = -D-STAR * 7 = -D-STAR
* 8 = +NXDN (non inverted voice frame) * 8 = +M17 STR (non inverted stream frame)
* 9 = -NXDN (inverted voice frame) * 9 = -M17 STR (inverted stream frame)
* 10 = +DMR (non inverted signal data frame) * 10 = +DMR (non inverted signal data frame)
* 11 = -DMR (inverted signal voice frame) * 11 = -DMR (inverted signal voice frame)
* 12 = +DMR (non inverted signal voice frame) * 12 = +DMR (non inverted signal voice frame)
* 13 = -DMR (inverted signal data frame) * 13 = -DMR (inverted signal data frame)
* 14 = +ProVoice * 14 = +ProVoice
* 15 = -ProVoice * 15 = -ProVoice
* 16 = +NXDN (non inverted data frame) * 16 = +M17 LSF (non inverted link frame)
* 17 = -NXDN (inverted data frame) * 17 = -M17 LSF (inverted link frame)
* 18 = +D-STAR_HD * 18 = +D-STAR_HD
* 19 = -D-STAR_HD * 19 = -D-STAR_HD
* 20 = +dPMR Frame Sync 1 * 20 = +dPMR Frame Sync 1
@@ -215,6 +215,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
char synctest20[21]; //YSF char synctest20[21]; //YSF
char synctest21[22]; //P25 S-OEMI (SACCH) char synctest21[22]; //P25 S-OEMI (SACCH)
char synctest48[49]; //EDACS char synctest48[49]; //EDACS
char synctest8[9]; //M17
char synctest16[17]; //M17 Preamble
char modulation[8]; char modulation[8];
char *synctest_p; char *synctest_p;
int symboltest_pos; //symbol test position, match to synctest_pos int symboltest_pos; //symbol test position, match to synctest_pos
@@ -228,13 +230,21 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{ {
t_max = 10; t_max = 10;
} }
//else if dPMR //dPMR
else if (opts->frame_dpmr == 1) else if (opts->frame_dpmr == 1)
{ {
t_max = 12; //based on Frame_Sync_2 pattern t_max = 12; //based on Frame_Sync_2 pattern
} }
//if Phase 2 (or YSF in future), then only 19 else if (opts->frame_m17 == 1)
else if (state->lastsynctype == 35 || state->lastsynctype == 36) //P2 {
t_max = 8;
}
else if (state->lastsynctype == 30 || state->lastsynctype == 31 )
{
t_max = 20; //20 on YSF
}
//if Phase 2, then only 19
else if (state->lastsynctype == 35 || state->lastsynctype == 36 )
{ {
t_max = 19; //Phase 2 S-ISCH is only 19 t_max = 19; //Phase 2 S-ISCH is only 19
} }
@@ -450,15 +460,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//if using an rtl input method, do not look for sync patterns if the rms value is lower than our 'soft squelch' level //if using an rtl input method, do not look for sync patterns if the rms value is lower than our 'soft squelch' level
if (opts->audio_in_type == 3 && opts->rtl_rms < opts->rtl_squelch_level) //tests show floor level around 40, and signal breaking 100, default is 100 for level if (opts->audio_in_type == 3 && opts->rtl_rms < opts->rtl_squelch_level)
{ {
if (opts->frame_nxdn48 == 1 || opts->frame_nxdn96 == 1 || opts->frame_dpmr == 1) if (opts->frame_nxdn48 == 1 || opts->frame_nxdn96 == 1 || opts->frame_dpmr == 1 || opts->frame_m17 == 1)
{ {
//should we update min/max here? yes or no?
// state->max = ((state->max) + lmax) / 2;
// state->min = ((state->min) + lmin) / 2;
goto SYNC_TEST_END; goto SYNC_TEST_END;
} }
} }
@@ -573,51 +578,138 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} }
} }
//YSF sync //YSF sync
strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right strncpy(synctest20, (synctest_p - 19), 20);
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1 if(opts->frame_ysf == 1)
{
if (0 == 0) //opts->inverted_ysf == 0
{ {
if (strcmp(synctest20, FUSION_SYNC) == 0) if (strcmp(synctest20, FUSION_SYNC) == 0)
{ {
printFrameSync (opts, state, "+YSF ", synctest_pos + 1, modulation);
state->carrier = 1; state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
fprintf (stderr, "\nYSF FUSION SYNC \n"); opts->inverted_ysf = 0;
opts->inverted_ysf = 0; //should we set this here?
state->lastsynctype = 30; state->lastsynctype = 30;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (30); return (30);
} }
} else if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
}
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
{
if (0 == 0) //opts->inverted_ysf == 1
{
if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
{ {
printFrameSync (opts, state, "-YSF ", synctest_pos + 1, modulation);
state->carrier = 1; state->carrier = 1;
state->offset = synctest_pos; state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2; state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2; state->min = ((state->min) + lmin) / 2;
fprintf (stderr, "\nINVERTED YSF FUSION SYNC \n"); opts->inverted_ysf = 1;
opts->inverted_ysf = 1; //should we set this here?
state->lastsynctype = 31; state->lastsynctype = 31;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (31); return (31);
} }
} }
}
//end YSF sync //end YSF sync
//M17 Sync -- Just STR and LSF for now
strncpy(synctest16, (synctest_p - 15), 16);
strncpy(synctest8, (synctest_p - 7), 8);
if(opts->frame_m17 == 1)
{
//preambles will skip dibits in an attempt to prime the
//demodulator but not attempt any decoding
if (strcmp(synctest8, M17_PRE) == 0)
{
if (opts->inverted_m17 == 0)
{
printFrameSync (opts, state, "+M17 PREAMBLE", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 98;
fprintf (stderr, "\n");
return (98);
}
}
else if (strcmp(synctest8, M17_PIV) == 0)
{
if (opts->inverted_m17 == 1)
{
printFrameSync (opts, state, "-M17 PREAMBLE", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
state->lastsynctype = 99;
fprintf (stderr, "\n");
return (99);
}
}
else if (strcmp(synctest8, M17_STR) == 0)
{
if (opts->inverted_m17 == 0)
{
printFrameSync (opts, state, "+M17 STR", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 16 || state->lastsynctype == 8)
{
state->lastsynctype = 16;
return (16);
}
state->lastsynctype = 16;
fprintf (stderr, "\n");
}
else
{
printFrameSync (opts, state, "-M17 LSF", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 99)
{
state->lastsynctype = 9;
return (9);
}
state->lastsynctype = 9;
fprintf (stderr, "\n");
}
}
else if (strcmp(synctest8, M17_LSF) == 0)
{
if (opts->inverted_m17 == 1)
{
printFrameSync (opts, state, "-M17 STR", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 17 || state->lastsynctype == 9)
{
state->lastsynctype = 17;
return (17);
}
state->lastsynctype = 17;
fprintf (stderr, "\n");
}
else
{
printFrameSync (opts, state, "+M17 LSF", synctest_pos + 1, modulation);
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->lastsynctype == 98)
{
state->lastsynctype = 8;
return (8);
}
state->lastsynctype = 8;
fprintf (stderr, "\n");
}
}
}
//end M17
//P25 P2 sync S-ISCH VCH //P25 P2 sync S-ISCH VCH
strncpy(synctest20, (synctest_p - 19), 20); strncpy(synctest20, (synctest_p - 19), 20);
if(opts->frame_p25p2 == 1) if(opts->frame_p25p2 == 1)

View File

@@ -26,6 +26,8 @@
#include "provoice_const.h" #include "provoice_const.h"
#include "git_ver.h" #include "git_ver.h"
volatile uint8_t exitflag; //fix for issue #136
int pretty_colors() int pretty_colors()
{ {
fprintf (stderr,"%sred\n", KRED); fprintf (stderr,"%sred\n", KRED);
@@ -51,7 +53,7 @@ char * FM_banner[9] = {
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║", " ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
" ██║ ██║╚█████╗ ██║ ██║ Lima ███║ ███╔═╝", " ██║ ██║╚█████╗ ██║ ██║ Lima ███║ ███╔═╝",
" ██║ ██║ ╚═══██╗██║ ██║ Zulu ███║ ██╔══╝ ", " ██║ ██║ ╚═══██╗██║ ██║ Zulu ███║ ██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝ Edition V ████████╗███████╗", " ██████╔╝██████╔╝██████╔╝ Edition VI ████████╗███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═══════╝╚══════╝", " ╚═════╝ ╚═════╝ ╚═════╝ ╚═══════╝╚══════╝",
" " " "
}; };
@@ -445,6 +447,35 @@ noCarrier (dsd_opts * opts, dsd_state * state)
sprintf (state->dpmr_caller_id, "%s", " "); sprintf (state->dpmr_caller_id, "%s", " ");
sprintf (state->dpmr_target_id, "%s", " "); sprintf (state->dpmr_target_id, "%s", " ");
//YSF Fusion Call Strings
sprintf (state->ysf_tgt, "%s", " "); //10 spaces
sprintf (state->ysf_src, "%s", " "); //10 spaces
sprintf (state->ysf_upl, "%s", " "); //10 spaces
sprintf (state->ysf_dnl, "%s", " "); //10 spaces
sprintf (state->ysf_rm1, "%s", " "); //5 spaces
sprintf (state->ysf_rm2, "%s", " "); //5 spaces
sprintf (state->ysf_rm3, "%s", " "); //5 spaces
sprintf (state->ysf_rm4, "%s", " "); //5 spaces
memset (state->ysf_txt, 0, sizeof(state->ysf_txt));
state->ysf_dt = 9;
state->ysf_fi = 9;
state->ysf_cm = 9;
//M17 Storage
memset (state->m17_lsf, 1, sizeof(state->m17_lsf));
state->m17_str_dt = 9;
state->m17_dst = 0;
state->m17_src = 0;
memset(state->m17_dst_csd, 0, sizeof(state->m17_dst_csd));
memset(state->m17_src_csd, 0, sizeof(state->m17_src_csd));
sprintf (state->m17_dst_str, "%s", "");
sprintf (state->m17_src_str, "%s", "");
state->m17_enc = 0;
state->m17_enc_st = 0;
memset(state->m17_meta, 0, sizeof(state->m17_meta));
} //nocarrier } //nocarrier
void void
@@ -520,13 +551,15 @@ initOpts (dsd_opts * opts)
opts->frame_dmr = 1; opts->frame_dmr = 1;
opts->frame_dpmr = 0; opts->frame_dpmr = 0;
opts->frame_provoice = 0; opts->frame_provoice = 0;
opts->frame_ysf = 0; //forgot to init this, and Cygwin treated as it was turned on. opts->frame_ysf = 1;
opts->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
opts->uvquality = 3; opts->uvquality = 3;
opts->inverted_x2tdma = 1; // most transmitter + scanner + sound card combinations show inverted signals for this opts->inverted_x2tdma = 1; // most transmitter + scanner + sound card combinations show inverted signals for this
opts->inverted_dmr = 0; // most transmitter + scanner + sound card combinations show non-inverted signals for this opts->inverted_dmr = 0; // most transmitter + scanner + sound card combinations show non-inverted signals for this
opts->inverted_m17 = 0; //samples from M17_Education seem to all be positive polarity (same from m17-tools programs)
opts->mod_threshold = 26; opts->mod_threshold = 26;
opts->ssize = 128; //36 default, max is 128, much cleaner data decodes on Phase 2 cqpsk at max opts->ssize = 128; //36 default, max is 128, much cleaner data decodes on Phase 2 cqpsk at max
opts->msize = 1024; //15 default, max is 1024, much cleaner data decodes on Phase 2 cqpsk at max opts->msize = 1024; //15 default, max is 1024, much cleaner data decodes on Phase 2 cqpsk at max
@@ -1011,6 +1044,41 @@ initState (dsd_state * state)
sprintf (state->dpmr_caller_id, "%s", " "); sprintf (state->dpmr_caller_id, "%s", " ");
sprintf (state->dpmr_target_id, "%s", " "); sprintf (state->dpmr_target_id, "%s", " ");
//YSF Fusion Call Strings
sprintf (state->ysf_tgt, "%s", " "); //10 spaces
sprintf (state->ysf_src, "%s", " "); //10 spaces
sprintf (state->ysf_upl, "%s", " "); //10 spaces
sprintf (state->ysf_dnl, "%s", " "); //10 spaces
sprintf (state->ysf_rm1, "%s", " "); //5 spaces
sprintf (state->ysf_rm2, "%s", " "); //5 spaces
sprintf (state->ysf_rm3, "%s", " "); //5 spaces
sprintf (state->ysf_rm4, "%s", " "); //5 spaces
memset (state->ysf_txt, 0, sizeof(state->ysf_txt));
state->ysf_dt = 9;
state->ysf_fi = 9;
state->ysf_cm = 9;
//M17 Storage
memset (state->m17_lsf, 1, sizeof(state->m17_lsf));
state->m17_str_dt = 9;
state->m17_dst = 0;
state->m17_src = 0;
memset(state->m17_dst_csd, 0, sizeof(state->m17_dst_csd));
memset(state->m17_src_csd, 0, sizeof(state->m17_src_csd));
sprintf (state->m17_dst_str, "%s", "");
sprintf (state->m17_src_str, "%s", "");
state->m17_enc = 0;
state->m17_enc_st = 0;
memset(state->m17_meta, 0, sizeof(state->m17_meta));
#ifdef USE_CODEC2
state->codec2_3200 = codec2_create(CODEC2_MODE_3200);
state->codec2_1600 = codec2_create(CODEC2_MODE_1600);
#endif
} //init_state } //init_state
void void
@@ -1095,6 +1163,8 @@ usage ()
printf (" -f2 Decode only P25 Phase 2 (6000 sps) **\n"); printf (" -f2 Decode only P25 Phase 2 (6000 sps) **\n");
printf (" -fd Decode only D-STAR\n"); printf (" -fd Decode only D-STAR\n");
printf (" -fx Decode only X2-TDMA\n"); printf (" -fx Decode only X2-TDMA\n");
printf (" -fy Decode only YSF\n");
printf (" -fz Decode only M17*\n");
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n"); printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
printf (" -fn Decode only NXDN96* (12.5 kHz)\n"); printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
printf (" -fp Decode only EDACS/ProVoice*\n"); printf (" -fp Decode only EDACS/ProVoice*\n");
@@ -1104,6 +1174,7 @@ usage ()
printf (" -xx Expect non-inverted X2-TDMA signal\n"); printf (" -xx Expect non-inverted X2-TDMA signal\n");
printf (" -xr Expect inverted DMR signal\n"); printf (" -xr Expect inverted DMR signal\n");
printf (" -xd Expect inverted ICOM dPMR signal\n"); printf (" -xd Expect inverted ICOM dPMR signal\n");
printf (" -xz Expect inverted M17 signal\n");
printf ("\n"); printf ("\n");
printf (" * denotes frame types that cannot be auto-detected.\n"); printf (" * denotes frame types that cannot be auto-detected.\n");
printf (" ** Phase 2 Single Frequency may require user to manually set WACN/SYSID/CC parameters if MAC_SIGNAL not present.\n"); printf (" ** Phase 2 Single Frequency may require user to manually set WACN/SYSID/CC parameters if MAC_SIGNAL not present.\n");
@@ -1120,8 +1191,8 @@ usage ()
printf (" (default=36)\n"); printf (" (default=36)\n");
printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n"); printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n");
printf (" (default=15)\n"); printf (" (default=15)\n");
printf (" -ma Auto-select modulation optimizations (default)\n"); printf (" -ma Auto-select modulation optimizations\n");
printf (" -mc Use only C4FM modulation optimizations\n"); printf (" -mc Use only C4FM modulation optimizations (default)\n");
printf (" -mg Use only GFSK modulation optimizations\n"); printf (" -mg Use only GFSK modulation optimizations\n");
printf (" -mq Use only QPSK modulation optimizations\n"); printf (" -mq Use only QPSK modulation optimizations\n");
printf (" -m2 Use P25p2 6000 sps QPSK modulation optimizations\n"); printf (" -m2 Use P25p2 6000 sps QPSK modulation optimizations\n");
@@ -1296,6 +1367,11 @@ if (opts->audio_out_type == 0)
void void
cleanupAndExit (dsd_opts * opts, dsd_state * state) cleanupAndExit (dsd_opts * opts, dsd_state * state)
{ {
#ifdef USE_CODEC2
codec2_destroy(state->codec2_1600);
codec2_destroy(state->codec2_3200);
#endif
noCarrier (opts, state); noCarrier (opts, state);
if (opts->wav_out_f != NULL) if (opts->wav_out_f != NULL)
{ {
@@ -1365,7 +1441,7 @@ main (int argc, char **argv)
mbe_printVersion (versionstr); mbe_printVersion (versionstr);
#ifdef LIMAZULUTWEAKS #ifdef LIMAZULUTWEAKS
fprintf (stderr," Digital Speech Decoder: LimaZulu Edition V\n"); fprintf (stderr," Digital Speech Decoder: LimaZulu Edition VI\n");
#else #else
fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n"); fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n");
#endif #endif
@@ -1374,7 +1450,7 @@ main (int argc, char **argv)
} }
#ifdef AERO_BUILD #ifdef AERO_BUILD
fprintf (stderr, "Build Version: v2.1 \n"); fprintf (stderr, "Build Version: v2.1b (20230714)\n");
#else #else
fprintf (stderr, "Build Version: %s \n", GIT_TAG); fprintf (stderr, "Build Version: %s \n", GIT_TAG);
#endif #endif
@@ -1742,11 +1818,12 @@ main (int argc, char **argv)
opts.frame_dmr = 1; opts.frame_dmr = 1;
opts.frame_dpmr = 0; opts.frame_dpmr = 0;
opts.frame_provoice = 0; opts.frame_provoice = 0;
opts.frame_ysf = 0; opts.frame_ysf = 1;
opts.frame_m17 = 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 = 48000; // /dev/dsp does need this set to 48000 to properly process the upsampling
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; //switching in 'stereo' for 'mono'
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");
@@ -1763,6 +1840,7 @@ 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.frame_m17 = 0;
opts.pulse_digi_rate_out = 48000; opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1; opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0; opts.dmr_stereo = 0;
@@ -1784,6 +1862,7 @@ 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.frame_m17 = 0;
opts.pulse_digi_rate_out = 48000; opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1; opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0; opts.dmr_stereo = 0;
@@ -1804,6 +1883,7 @@ main (int argc, char **argv)
opts.frame_dpmr = 0; opts.frame_dpmr = 0;
opts.frame_provoice = 1; opts.frame_provoice = 1;
opts.frame_ysf = 0; opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 5; state.samplesPerSymbol = 5;
state.symbolCenter = 2; state.symbolCenter = 2;
opts.mod_c4fm = 0; opts.mod_c4fm = 0;
@@ -1835,6 +1915,7 @@ 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.frame_m17 = 0;
opts.dmr_stereo = 0; opts.dmr_stereo = 0;
state.dmr_stereo = 0; state.dmr_stereo = 0;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
@@ -1864,6 +1945,7 @@ 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.frame_m17 = 0;
state.samplesPerSymbol = 20; state.samplesPerSymbol = 20;
state.symbolCenter = 10; state.symbolCenter = 10;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
@@ -1893,8 +1975,7 @@ main (int argc, char **argv)
opts.frame_dpmr = 0; opts.frame_dpmr = 0;
opts.frame_provoice = 0; opts.frame_provoice = 0;
opts.frame_ysf = 1; opts.frame_ysf = 1;
state.samplesPerSymbol = 20; //10 opts.frame_m17 = 0;
state.symbolCenter = 10;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
opts.mod_qpsk = 0; opts.mod_qpsk = 0;
opts.mod_gfsk = 0; opts.mod_gfsk = 0;
@@ -1905,8 +1986,7 @@ main (int argc, char **argv)
state.dmr_stereo = 0; state.dmr_stereo = 0;
opts.dmr_mono = 0; opts.dmr_mono = 0;
sprintf (opts.output_name, "YSF"); sprintf (opts.output_name, "YSF");
fprintf (stderr,"Setting symbol rate to 2400 / second\n"); fprintf (stderr,"Decoding only YSF frames. \n");
fprintf (stderr,"Decoding only YSF frames.\nNot working yet!\n");
} }
else if (optarg[0] == '2') else if (optarg[0] == '2')
{ {
@@ -1920,6 +2000,7 @@ 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.frame_m17 = 0;
state.samplesPerSymbol = 8; state.samplesPerSymbol = 8;
state.symbolCenter = 3; state.symbolCenter = 3;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
@@ -1946,6 +2027,7 @@ 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.frame_m17 = 0;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
opts.mod_qpsk = 0; opts.mod_qpsk = 0;
opts.mod_gfsk = 0; opts.mod_gfsk = 0;
@@ -1971,7 +2053,8 @@ main (int argc, char **argv)
opts.frame_dmr = 1; opts.frame_dmr = 1;
opts.frame_dpmr = 0; opts.frame_dpmr = 0;
opts.frame_provoice = 0; opts.frame_provoice = 0;
opts.frame_ysf = 0; opts.frame_ysf = 1;
opts.frame_m17 = 0;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
opts.mod_qpsk = 0; opts.mod_qpsk = 0;
opts.mod_gfsk = 0; opts.mod_gfsk = 0;
@@ -1998,6 +2081,7 @@ 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.frame_m17 = 0;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
opts.mod_qpsk = 0; opts.mod_qpsk = 0;
opts.mod_gfsk = 0; opts.mod_gfsk = 0;
@@ -2023,6 +2107,7 @@ 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.frame_m17 = 0;
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
opts.mod_qpsk = 0; opts.mod_qpsk = 0;
opts.mod_gfsk = 0; // opts.mod_gfsk = 0; //
@@ -2049,7 +2134,8 @@ main (int argc, char **argv)
opts.frame_dmr = 0; opts.frame_dmr = 0;
opts.frame_provoice = 0; opts.frame_provoice = 0;
opts.frame_dpmr = 1; opts.frame_dpmr = 1;
opts.frame_ysf = 0; //testing with NXDN48 parameters opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 20; //same as NXDN48 - 20 state.samplesPerSymbol = 20; //same as NXDN48 - 20
state.symbolCenter = 10; //same as NXDN48 - 10 state.symbolCenter = 10; //same as NXDN48 - 10
opts.mod_c4fm = 1; opts.mod_c4fm = 1;
@@ -2065,6 +2151,32 @@ main (int argc, char **argv)
fprintf(stderr, "Notice: dPMR cannot autodetect polarity. \n Use -xd option if Inverted Signal expected.\n"); fprintf(stderr, "Notice: dPMR cannot autodetect polarity. \n Use -xd option if Inverted Signal expected.\n");
fprintf(stderr, "Decoding only dPMR frames.\n"); fprintf(stderr, "Decoding only dPMR frames.\n");
} }
else if (optarg[0] == 'z') //placeholder letter
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_p25p2 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
opts.frame_dpmr = 0;
opts.frame_ysf = 0;
opts.frame_m17 = 1;
opts.mod_c4fm = 1;
opts.mod_qpsk = 0;
opts.mod_gfsk = 0;
state.rf_mod = 0;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
sprintf (opts.output_name, "M17");
fprintf(stderr, "Notice: M17 cannot autodetect polarity. \n Use -xz option if Inverted Signal expected.\n");
fprintf(stderr, "Decoding only M17 frames.\n");
}
break; break;
//don't mess with the modulations unless you really need to //don't mess with the modulations unless you really need to
case 'm': case 'm':
@@ -2164,6 +2276,11 @@ main (int argc, char **argv)
opts.inverted_dpmr = 1; opts.inverted_dpmr = 1;
fprintf (stderr, "Expecting inverted ICOM dPMR signals.\n"); fprintf (stderr, "Expecting inverted ICOM dPMR signals.\n");
} }
else if (optarg[0] == 'z')
{
opts.inverted_m17 = 1;
fprintf (stderr, "Expecting inverted M17 signals.\n");
}
break; break;
case 'A': case 'A':
sscanf (optarg, "%i", &opts.mod_threshold); sscanf (optarg, "%i", &opts.mod_threshold);
@@ -2365,6 +2482,7 @@ main (int argc, char **argv)
int fmt; int fmt;
int speed = 48000; int speed = 48000;
//NOTE: Both /dev/audio AND /dev/dsp randomly open multiple input streams in Linux under padsp wrapper //NOTE: Both /dev/audio AND /dev/dsp randomly open multiple input streams in Linux under padsp wrapper
if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0)) if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
{ {
@@ -2412,6 +2530,10 @@ main (int argc, char **argv)
opts.audio_in_type = 5; //5 will become OSS input type opts.audio_in_type = 5; //5 will become OSS input type
} }
//Codec2 only running at 8k output currently, need to match for OSS
if (opts.frame_m17 == 1)
speed = 8000;
if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0)) if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0))
{ {
sprintf (opts.audio_out_dev, "%s", "/dev/dsp"); sprintf (opts.audio_out_dev, "%s", "/dev/dsp");

View File

@@ -1058,9 +1058,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
} }
#endif #endif
state->debug_audio_errors += state->errs2 + state->errs;
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;
if (opts->audio_out == 1) if (opts->audio_out == 1)
{ {
processAudio(opts, state); processAudio(opts, state);
@@ -1128,9 +1129,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
} }
#endif #endif
state->debug_audio_errorsR += state->errs2R + state->errsR;
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;
if (opts->audio_out == 1) if (opts->audio_out == 1)
{ {
processAudioR(opts, state); processAudioR(opts, state);
@@ -1145,7 +1147,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types //if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
if (opts->dmr_mono == 0 && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) ) if (opts->dmr_mono == 0 && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) )
{ {
state->debug_audio_errors += state->errs2; state->debug_audio_errors += state->errs2 + state->errs;
if (opts->audio_out == 1) if (opts->audio_out == 1)
{ {
processAudio(opts, state); processAudio(opts, state);

View File

@@ -85,7 +85,7 @@ char * SyncTypes[44] = {
"NXDN", "NXDN",
"NXDN", "NXDN",
"YSF", //30 "YSF", //30
"YSF", "YSF", //31
"DMR", "DMR",
"DMR", "DMR",
"DMR", "DMR",
@@ -301,7 +301,7 @@ char * getTimeC(time_t t) //get pretty hh:mm:ss timestamp
//testing a few things, going to put this into ncursesMenu //testing a few things, going to put this into ncursesMenu
#define WIDTH 36 #define WIDTH 36
#define HEIGHT 23 #define HEIGHT 25
int startx = 0; int startx = 0;
int starty = 0; int starty = 0;
@@ -338,7 +338,8 @@ char *choices[] = {
"Decode dPMR", "Decode dPMR",
"Decode NXDN48", "Decode NXDN48",
"Decode NXDN96", "Decode NXDN96",
"Decode DMR Stereo", //was X2-TDMA* "Decode DMR TDMA",
"Decode YSF FUSION",
"Toggle Signal Inversion", "Toggle Signal Inversion",
"Key Entry", "Key Entry",
"Reset Call History", "Reset Call History",
@@ -542,7 +543,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
info_win = newwin(6, WIDTH+18, starty, startx+20); info_win = newwin(6, WIDTH+18, starty, startx+20);
box (info_win, 0, 0); box (info_win, 0, 0);
mvwprintw(info_win, 2, 2, " Legacy Auto can only detect the following:"); mvwprintw(info_win, 2, 2, " Legacy Auto can only detect the following:");
mvwprintw(info_win, 3, 2, " P25-P1, D-STAR, DMR Mono, and X2-TDMA"); mvwprintw(info_win, 3, 2, " P25p1, D-STAR, DMR Mono, YSF, and X2-TDMA");
wrefresh(info_win); wrefresh(info_win);
} }
@@ -551,13 +552,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
info_win = newwin(7, WIDTH+18, starty, startx+20); info_win = newwin(7, WIDTH+18, starty, startx+20);
box (info_win, 0, 0); box (info_win, 0, 0);
mvwprintw(info_win, 2, 2, " XDMA Decoding Class Supports the following:"); mvwprintw(info_win, 2, 2, " XDMA Decoding Class Supports the following:");
mvwprintw(info_win, 3, 2, " P25-P1, P25-P2, and DMR Stereo BS/MS"); mvwprintw(info_win, 3, 2, " P25p1, P25p2, YSF, and DMR BS/MS");
mvwprintw(info_win, 4, 2, " --C4FM / FSK4 only, and OP25 P2 Capture Bins"); mvwprintw(info_win, 4, 2, " C4FM, FSK4, QPSK only (no H8D-QPSK)");
wrefresh(info_win); wrefresh(info_win);
} }
//Input Output Options //Input Output Options
if (choice == 17) if (choice == 18)
{ {
//test making a new window while other window is open //test making a new window while other window is open
test_win = newwin(HEIGHT-1, WIDTH+9, starty+5, startx+5); test_win = newwin(HEIGHT-1, WIDTH+9, starty+5, startx+5);
@@ -1086,7 +1087,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
} }
//Privacy Key Entry //Privacy Key Entry
if (choice == 13) if (choice == 14)
{ {
state->payload_keyid = 0; state->payload_keyid = 0;
state->payload_keyidR = 0; state->payload_keyidR = 0;
@@ -1259,7 +1260,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->frame_dmr = 1; opts->frame_dmr = 1;
opts->frame_dpmr = 0; opts->frame_dpmr = 0;
opts->frame_provoice = 0; opts->frame_provoice = 0;
opts->frame_ysf = 0; opts->frame_ysf = 1;
opts->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1290,6 +1292,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->frame_dpmr = 0; opts->frame_dpmr = 0;
opts->frame_provoice = 1; opts->frame_provoice = 1;
opts->frame_ysf = 0; opts->frame_ysf = 0;
opts->frame_m17 = 0;
opts->mod_c4fm = 0; opts->mod_c4fm = 0;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 1; opts->mod_gfsk = 1;
@@ -1318,6 +1321,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1356,6 +1360,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1392,7 +1397,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->frame_nxdn96 = 0; opts->frame_nxdn96 = 0;
opts->frame_dpmr = 0; opts->frame_dpmr = 0;
opts->frame_provoice = 0; opts->frame_provoice = 0;
opts->frame_ysf = 0; opts->frame_ysf = 1;
opts->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1420,6 +1426,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1447,6 +1454,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->frame_dpmr = 1; opts->frame_dpmr = 1;
opts->frame_provoice = 0; opts->frame_provoice = 0;
opts->frame_ysf = 0; opts->frame_ysf = 0;
opts->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1477,6 +1485,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
//opts->unmute_encrypted_p25 = 0; //opts->unmute_encrypted_p25 = 0;
// opts->mod_qpsk = 0; // opts->mod_qpsk = 0;
@@ -1504,6 +1513,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1532,6 +1542,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
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->frame_m17 = 0;
opts->mod_c4fm = 1; opts->mod_c4fm = 1;
opts->mod_qpsk = 0; opts->mod_qpsk = 0;
opts->mod_gfsk = 0; opts->mod_gfsk = 0;
@@ -1539,6 +1550,60 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
//opts->unmute_encrypted_p25 = 0; //opts->unmute_encrypted_p25 = 0;
} }
if (choice == 12) if (choice == 12)
{
//Decode YSF Fusion
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (opts->output_name, "YSF");
opts->dmr_mono = 0;
opts->dmr_stereo = 0; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
opts->pulse_digi_rate_out = 48000;
opts->pulse_digi_out_channels = 1;
opts->frame_dstar = 0;
opts->frame_x2tdma = 0;
opts->frame_p25p1 = 0;
opts->frame_nxdn48 = 0;
opts->frame_nxdn96 = 0;
opts->frame_dmr = 0;
opts->frame_dpmr = 0;
opts->frame_provoice = 0;
opts->frame_ysf = 1;
opts->frame_m17 = 0;
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
}
if (choice == 99) //TODO: Slot this into the menu choices, and maybe rearrange them into the correct order as well
{
//Decode M17
// resetState (state); //use sparingly, may cause memory leak
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (opts->output_name, "M17");
opts->dmr_mono = 0;
opts->dmr_stereo = 0; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
opts->pulse_digi_rate_out = 8000;
opts->pulse_digi_out_channels = 1;
opts->frame_dstar = 0;
opts->frame_x2tdma = 0;
opts->frame_p25p1 = 0;
opts->frame_nxdn48 = 0;
opts->frame_nxdn96 = 0;
opts->frame_dmr = 0;
opts->frame_dpmr = 0;
opts->frame_provoice = 0;
opts->frame_ysf = 0;
opts->frame_m17 = 1;
opts->mod_c4fm = 1;
opts->mod_qpsk = 0;
opts->mod_gfsk = 0;
state->rf_mod = 0;
}
if (choice == 13)
{ {
//Set all signal for inversion or uninversion //Set all signal for inversion or uninversion
if (opts->inverted_dmr == 0) if (opts->inverted_dmr == 0)
@@ -1547,6 +1612,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->inverted_dpmr = 1; opts->inverted_dpmr = 1;
opts->inverted_x2tdma = 1; opts->inverted_x2tdma = 1;
opts->inverted_ysf = 1; opts->inverted_ysf = 1;
opts->inverted_m17 = 1;
} }
else else
{ {
@@ -1554,10 +1620,11 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->inverted_dpmr = 0; opts->inverted_dpmr = 0;
opts->inverted_x2tdma = 0; opts->inverted_x2tdma = 0;
opts->inverted_ysf = 0; opts->inverted_ysf = 0;
opts->inverted_m17 = 0;
} }
} }
if (choice == 14) //reset call history (usually if janky output when switching modes) if (choice == 15) //reset call history (usually if janky output when switching modes)
{ {
for (short int k = 0; k <= 9; k++) for (short int k = 0; k <= 9; k++)
{ {
@@ -1582,7 +1649,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->lasttgR = 0; state->lasttgR = 0;
} }
if (choice == 15) //toggle payload printing if (choice == 16) //toggle payload printing
{ {
if (opts->payload == 0) if (opts->payload == 0)
{ {
@@ -1595,7 +1662,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
fprintf(stderr, "Payload Off\n"); fprintf(stderr, "Payload Off\n");
} }
} }
if (choice == 16) if (choice == 17)
{ {
//hardset P2 WACN, SYSID, and NAC //hardset P2 WACN, SYSID, and NAC
entry_win = newwin(6, WIDTH+16, starty+10, startx+10); entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
@@ -1648,7 +1715,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
} }
if (choice == 18) if (choice == 19)
{ {
short int lrrpchoice = 0; short int lrrpchoice = 0;
entry_win = newwin(10, WIDTH+16, starty+10, startx+10); entry_win = newwin(10, WIDTH+16, starty+10, startx+10);
@@ -1714,7 +1781,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->lrrp_out_file[0] = 0; opts->lrrp_out_file[0] = 0;
} }
} }
if (choice == 19) if (choice == 20)
{ {
ncursesClose(); ncursesClose();
//cleanup_rtlsdr_stream(); //cleanup_rtlsdr_stream();
@@ -1754,7 +1821,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
rtl_clean_queue(); rtl_clean_queue();
reset_dibit_buffer(state); //test and observe for any random issues, disable if needed reset_dibit_buffer(state); //test and observe for any random issues, disable if needed
#elif AERO_BUILD #elif AERO_BUILD
opts->audio_out_type = 3; //hopefully the audio stream is still/already open opts->audio_out_type = 5; //hopefully the audio stream is still/already open //shouldn't this be 5? Was set to 3
#else #else
opts->audio_out_type = 0; //need to see if we need to open pulseoutput as well here? opts->audio_out_type = 0; //need to see if we need to open pulseoutput as well here?
openPulseOutput (opts); openPulseOutput (opts);
@@ -2158,14 +2225,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_compact == 1) if (opts->ncurses_compact == 1)
{ {
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.1 "); printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.1b (20230714)");
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
} }
#elif LIMAZULUTWEAKS #elif LIMAZULUTWEAKS
if (opts->ncurses_compact == 1) if (opts->ncurses_compact == 1)
{ {
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: LimaZulu Edition V: The Empire Strikes Back \n"); printw ("| Digital Speech Decoder: LimaZulu Edition VI: Return of the Zulu \n");
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
} }
#elif ZDEV_BUILD #elif ZDEV_BUILD
@@ -2194,7 +2261,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (i == 4) printw (" MBElib %s", versionstr); if (i == 4) printw (" MBElib %s", versionstr);
#ifdef AERO_BUILD #ifdef AERO_BUILD
if (i == 5) printw (" %s ", "Aero Build"); if (i == 5) printw (" %s ", "Aero Build");
if (i == 6) printw (" v2.1 \n"); if (i == 6) printw (" v2.1b (20230714) \n");
#elif ZDEV_BUILD #elif ZDEV_BUILD
if (i == 5) printw (" %s ", "zDEV Build"); if (i == 5) printw (" %s ", "zDEV Build");
if (i == 6) printw (" %s \n", GIT_TAG); if (i == 6) printw (" %s \n", GIT_TAG);
@@ -2352,7 +2419,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
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
} }
@@ -2409,6 +2476,136 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
} }
//M17
if (lls == 8 || lls == 9 || lls == 16 || lls == 17)
{
printw ("| ");
printw ("M17 - ");
//insert data type and frame information
if (state->m17_str_dt == 0) printw("Reserved");
if (state->m17_str_dt == 1) printw("Data ");
if (state->m17_str_dt == 2) printw("Voice (3200) ");
if (state->m17_str_dt == 3) printw("Voice (1600) + Data");
printw (" ");
printw ("\n");
printw ("| ");
printw ("DST: ");
if (state->m17_dst == 0xFFFFFFFFFFFF)
printw("BROADCAST ");
else if (state->m17_dst != 0 && state->m17_dst >= 0xEE6B28000000)
printw("RESERVED (%012llx) ", state->m17_dst);
else
{
// for (i = 0; i < 9; i++)
// printw ("%c", state->m17_dst_csd[i]);
printw("%s", state->m17_dst_str);
}
printw ("\n");
printw ("| ");
printw ("SRC: ");
if (state->m17_src != 0 && state->m17_src >= 0xEE6B28000000)
printw("RESERVED (%012llx)", state->m17_src);
else
{
// for (i = 0; i < 9; i++)
// printw ("%c", state->m17_src_csd[i]);
printw("%s", state->m17_src_str);
}
printw ("\n");
printw ("| ");
//fill in any extra info, like Meta (IV, etc)
if (state->m17_enc == 2)
{
printw (" Scrambler - Type: %d", state->m17_enc_st);
}
if (state->m17_enc == 1)
{
printw (" AES-CTR - IV: ");
//display packed meta as IV
for (i = 0; i < 14; i++)
printw ("%02X", state->m17_meta[i]);
}
if (state->m17_enc == 3)
{
printw (" Reserved Enc - Type: %d", state->m17_enc_st);
}
printw ("\n");
}
//YSF
if (lls == 30 || lls == 31)
{
// printw ("\n");
printw ("| ");
printw ("Fusion - ");
//insert data type and frame information
if (state->ysf_dt == 0) printw("V/D1 ");
if (state->ysf_dt == 1) printw("DATA ");
if (state->ysf_dt == 2) printw("V/D2 ");
if (state->ysf_dt == 3) printw("VWFR ");
printw (" ");
if (state->ysf_cm == 0) printw("Group/CQ ");
if (state->ysf_cm == 3) printw("Private ");
if (state->ysf_cm == 1) printw("Radio ID ");
if (state->ysf_cm == 2) printw("Reserved ");
if (state->ysf_fi == 0) printw("HC ");
if (state->ysf_fi == 1) printw("CC ");
if (state->ysf_fi == 2) printw("TC ");
if (state->ysf_fi == 3) printw("XX ");
printw ("\n");
printw ("| ");
//NOTE: In Radio ID Mode, the DST will be split on Destination and Source Radio ID values
printw ("DST: %s ", state->ysf_tgt);
printw ("SRC: %s ", state->ysf_src);
printw ("\n");
printw ("| ");
printw ("UPL: %s ", state->ysf_upl);
printw ("DNL: %s ", state->ysf_dnl);
printw ("\n");
printw ("| ");
printw ("RM1: %s ", state->ysf_rm1);
printw ("RM2: %s ", state->ysf_rm2);
printw ("\n");
printw ("| ");
printw ("RM3: %s ", state->ysf_rm3);
printw ("RM4: %s ", state->ysf_rm4);
//these texts can get pretty long and out of sorts, and lots of 0x20 spaces
//just going to leave these to only be in the console output
// printw ("\n");
// printw ("| ");
// printw ("TXT: ");
// for (i = 4; i < 8; i++)
// {
// for (int j = 0; j < 20; j++)
// {
// //no spaces and no asterisks
// if (state->ysf_txt[i][j] != 0x2A)
// printw ("%c", state->ysf_txt[i][j]);
// }
// // printw (" "); //just a single space between each 'block'
// }
printw ("\n");
}
//NXDN //NXDN
if (lls == 28 || lls == 29) if (lls == 28 || lls == 29)
{ {
@@ -2424,7 +2621,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (idas == 1) printw ("Monitoring RTCH2 Channel"); //Idas RTCH2 Channel if (idas == 1) printw ("Monitoring RTCH2 Channel"); //Idas RTCH2 Channel
if (state->p25_cc_freq != 0) if (state->p25_cc_freq != 0)
{ {
printw (" - Frequency: [%.06lf] Mhz ", (double)state->p25_cc_freq/1000000); printw (" - Frequency: %.06lf Mhz ", (double)state->p25_cc_freq/1000000);
} }
} }
else if (opts->p25_is_tuned == 1) else if (opts->p25_is_tuned == 1)
@@ -2433,7 +2630,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (idas == 1) printw ("Monitoring RTCH2 Channel"); //Idas RTCH2 if (idas == 1) printw ("Monitoring RTCH2 Channel"); //Idas RTCH2
if (state->p25_vc_freq[0] != 0) if (state->p25_vc_freq[0] != 0)
{ {
printw (" - Frequency: [%.06lf] Mhz ", (double)state->p25_vc_freq[0]/1000000); printw (" - Frequency: %.06lf Mhz ", (double)state->p25_vc_freq[0]/1000000);
} }
} }
@@ -2443,13 +2640,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("| "); printw ("| ");
#ifdef LIMAZULUTWEAKS // #ifdef LIMAZULUTWEAKS
if (idas == 0) printw ("NXDN - RAN: [%02d] ", state->nxdn_last_ran); if (idas == 0) printw ("NXDN - RAN: [%02d] ", state->nxdn_last_ran);
if (idas == 1) printw ("IDAS - Area: [%02d] ", state->nxdn_last_ran); if (idas == 1) printw ("IDAS - Area: [%02d] ", state->nxdn_last_ran);
#else // #else
if (idas == 0) printw ("NXDN - RAN: [%02d] ", rn); // if (idas == 0) printw ("NXDN - RAN: [%02d] ", rn);
if (idas == 1) printw ("IDAS - Area: [%02d] ", rn); // if (idas == 1) printw ("IDAS - Area: [%02d] ", rn);
#endif // #endif
if (state->nxdn_location_site_code != 0) if (state->nxdn_location_site_code != 0)
{ {
printw ("Cat: [%s] ", state->nxdn_location_category); printw ("Cat: [%s] ", state->nxdn_location_category);
@@ -2581,15 +2778,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("%s", state->dmr_site_parms); //site id, net id, etc printw ("%s", state->dmr_site_parms); //site id, net id, etc
if (state->dmr_rest_channel > 0) if (state->dmr_rest_channel > 0)
{ {
printw ("Rest Channel: [%02d] ", state->dmr_rest_channel); printw ("Rest LSN: %02d; ", state->dmr_rest_channel);
if (state->trunk_chan_map[state->dmr_rest_channel] != 0) if (state->trunk_chan_map[state->dmr_rest_channel] != 0)
{ {
printw ("Freq: [%.06lf] Mhz", (double)state->trunk_chan_map[state->dmr_rest_channel]/1000000); printw ("Freq: %.06lf Mhz", (double)state->trunk_chan_map[state->dmr_rest_channel]/1000000);
} }
} }
else if (state->p25_cc_freq != 0) else if (state->p25_cc_freq != 0)
{ {
printw ("Freq: [%.06lf] MHz", (double)state->p25_cc_freq/1000000); printw ("Freq: %.06lf MHz", (double)state->p25_cc_freq/1000000);
} }
} }
@@ -2602,7 +2799,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("P25 P1 - [%05llX][%03llX][%03llX] RFSS: [%lld] SITE: [%lld] ", state->p2_wacn, state->p2_sysid, state->p2_cc, state->p2_rfssid, state->p2_siteid); printw ("P25 P1 - [%05llX][%03llX][%03llX] RFSS: [%lld] SITE: [%lld] ", state->p2_wacn, state->p2_sysid, state->p2_cc, state->p2_rfssid, state->p2_siteid);
if (state->p25_cc_freq != 0) if (state->p25_cc_freq != 0)
{ {
printw ("Freq: [%.06lf] MHz", (double)state->p25_cc_freq/1000000); printw ("Freq: %.06lf MHz", (double)state->p25_cc_freq/1000000);
} }
} }
else if (lls == 35 || lls == 36) //P2 else if (lls == 35 || lls == 36) //P2
@@ -2624,7 +2821,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
if (state->p25_cc_freq != 0) if (state->p25_cc_freq != 0)
{ {
printw ("Freq: [%.06lf] MHz", (double)state->p25_cc_freq/1000000); printw ("Freq: %.06lf MHz", (double)state->p25_cc_freq/1000000);
} }
} }
} }
@@ -2721,7 +2918,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("Double DES"); printw("Double DES");
attron(COLOR_PAIR(3)); attron(COLOR_PAIR(3));
} }
if (state->payload_algid == 0x83 || state->payload_algid == 0x23) if (state->payload_algid == 0x83)
{ {
attron(COLOR_PAIR(1)); attron(COLOR_PAIR(1));
printw("Triple DES"); printw("Triple DES");
@@ -2914,7 +3111,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("DES-OFB"); printw("DES-OFB");
attron(COLOR_PAIR(3)); attron(COLOR_PAIR(3));
} }
if (state->payload_algidR == 0x83 || state->payload_algidR == 0x23) if (state->payload_algidR == 0x83)
{ {
attron(COLOR_PAIR(1)); attron(COLOR_PAIR(1));
printw("Triple DES"); printw("Triple DES");
@@ -3049,7 +3246,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->p25_vc_freq[0] != 0) if (state->p25_vc_freq[0] != 0)
{ {
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
printw ("Frequency: [%.06lf] MHz ", (double)state->p25_vc_freq[0]/1000000); printw ("Frequency: %.06lf MHz ", (double)state->p25_vc_freq[0]/1000000);
} }
if (state->carrier == 1) attron(COLOR_PAIR(3)); if (state->carrier == 1) attron(COLOR_PAIR(3));
else attroff(COLOR_PAIR(4)); else attroff(COLOR_PAIR(4));
@@ -3363,6 +3560,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->inverted_dpmr = 1; opts->inverted_dpmr = 1;
opts->inverted_x2tdma = 1; opts->inverted_x2tdma = 1;
opts->inverted_ysf = 1; opts->inverted_ysf = 1;
opts->inverted_m17 = 1;
} }
else else
{ {
@@ -3370,6 +3568,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->inverted_dpmr = 0; opts->inverted_dpmr = 0;
opts->inverted_x2tdma = 0; opts->inverted_x2tdma = 0;
opts->inverted_ysf = 0; opts->inverted_ysf = 0;
opts->inverted_m17 = 0;
} }
} }

View File

@@ -111,7 +111,7 @@ 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"); fprintf (stderr, "\nEnd of %s\n", opts->audio_in_dev);
//open pulse input if we are pulse output AND using ncurses terminal //open pulse input if we are pulse output AND using ncurses terminal
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1) if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1)
{ {
@@ -247,43 +247,20 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
} }
//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
// else if (opts->audio_in_type == 6)
// {
//I think this doesn't get the entire dgram when we run sf_read_short on the udp dgram
// result = sf_read_short(opts->udp_file_in, &sample, 1);
// if (sample != 0)
// fprintf (stderr, "Result = %d Sample = %d \n", result, sample);
// }
if (opts->use_cosine_filter) if (opts->use_cosine_filter)
{ {
if ( (state->lastsynctype >= 10 && state->lastsynctype <= 13) || state->lastsynctype == 32 || state->lastsynctype == 33 || state->lastsynctype == 34) if ( (state->lastsynctype >= 10 && state->lastsynctype <= 13) || state->lastsynctype == 32 || state->lastsynctype == 33
|| state->lastsynctype == 34 || state->lastsynctype == 30 || state->lastsynctype == 31)
{ {
sample = dmr_filter(sample); sample = dmr_filter(sample);
} }
else if (state->lastsynctype == 8 || state->lastsynctype == 9 || else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||state->lastsynctype == 16 || state->lastsynctype == 17)
state->lastsynctype == 16 || state->lastsynctype == 17 || {
sample = m17_filter(sample);
}
else if (
state->lastsynctype == 20 || state->lastsynctype == 21 || state->lastsynctype == 20 || state->lastsynctype == 21 ||
state->lastsynctype == 22 || state->lastsynctype == 23 || state->lastsynctype == 22 || state->lastsynctype == 23 ||
state->lastsynctype == 24 || state->lastsynctype == 25 || state->lastsynctype == 24 || state->lastsynctype == 25 ||
@@ -522,7 +499,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{ {
// 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"); fprintf (stderr, "\nEnd of %s\n", opts->audio_in_dev);
//open pulse input if we are pulse output AND using ncurses terminal //open pulse input if we are pulse output AND using ncurses terminal
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1) if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1)
{ {

746
src/m17.c Normal file
View File

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

View File

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

View File

@@ -25,7 +25,9 @@
#include "dsd.h" #include "dsd.h"
#include "nxdn_const.h" #include "nxdn_const.h"
static const uint8_t scramble_t[] = { //values are the position values we need to invert in the descramble //NOTE: Descrambling was having an issue without a value inside the brackets, but only when
//the PARITY table was disabled, was this due to a memory issue or overflow?
static const uint8_t scramble_t[182] = { //values are the position values we need to invert in the descramble
2, 5, 6, 7, 10, 12, 14, 16, 17, 22, 23, 25, 26, 27, 28, 30, 33, 34, 36, 37, 38, 41, 45, 47, 2, 5, 6, 7, 10, 12, 14, 16, 17, 22, 23, 25, 26, 27, 28, 30, 33, 34, 36, 37, 38, 41, 45, 47,
52, 54, 56, 57, 59, 62, 63, 64, 65, 66, 67, 69, 70, 73, 76, 79, 81, 82, 84, 85, 86, 87, 88, 52, 54, 56, 57, 59, 62, 63, 64, 65, 66, 67, 69, 70, 73, 76, 79, 81, 82, 84, 85, 86, 87, 88,
89, 92, 95, 96, 98, 100, 103, 104, 107, 108, 116, 117, 121, 122, 125, 127, 131, 132, 134, 89, 92, 95, 96, 98, 100, 103, 104, 107, 108, 116, 117, 121, 122, 125, 127, 131, 132, 134,
@@ -33,11 +35,6 @@ static const uint8_t scramble_t[] = { //values are the position values we need t
168, 170, 171, 174, 175, 176, 177, 181 168, 170, 171, 174, 175, 176, 177, 181
}; };
static const int PARITY[] = {
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0,
1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1,
1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
//decoding functions here //decoding functions here
void nxdn_descramble(uint8_t dibits[], int len) void nxdn_descramble(uint8_t dibits[], int len)

View File

@@ -144,6 +144,10 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
NXDN_decode_VCALL(opts, state, ElementsContent); NXDN_decode_VCALL(opts, state, ElementsContent);
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment)); memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
#ifdef LIMAZULUTWEAKS
; //do nothing -- testing errors on CAC messages when returning quickly from RTCH
#else
//tune back to CC here - save about 1-2 seconds //tune back to CC here - save about 1-2 seconds
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
{ {
@@ -175,6 +179,7 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
state->last_cc_sync_time = time(NULL); //allow tuners a second to catch up, particularly rtl input state->last_cc_sync_time = time(NULL); //allow tuners a second to catch up, particularly rtl input
} }
#endif
break; break;
//Idle //Idle

View File

@@ -469,7 +469,7 @@ processHDU(dsd_opts* opts, dsd_state* state)
{ {
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3); fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2);
state->payload_algid = algidhex; state->payload_algid = algidhex;
state->payload_keyid = kidhex; state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA) if (state->R != 0 && state->payload_algid == 0xAA)
@@ -477,6 +477,11 @@ processHDU(dsd_opts* opts, dsd_state* state)
fprintf (stderr, " Key: %010llX", state->R); fprintf (stderr, " Key: %010llX", state->R);
opts->unmute_encrypted_p25 = 1; opts->unmute_encrypted_p25 = 1;
} }
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
{
//may want to mute this again, or may not want to
opts->unmute_encrypted_p25 = 0;
}
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3 //only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2); state->payload_miP = (mihex1 << 32) | (mihex2);

View File

@@ -371,7 +371,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
if (irrecoverable_errors == 0) if (irrecoverable_errors == 0)
{ {
fprintf (stderr, "%s", KYEL); fprintf (stderr, "%s", KYEL);
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3); fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2);
state->payload_algid = algidhex; state->payload_algid = algidhex;
state->payload_keyid = kidhex; state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA) if (state->R != 0 && state->payload_algid == 0xAA)
@@ -379,6 +379,11 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " Key: %010llX", state->R); fprintf (stderr, " Key: %010llX", state->R);
opts->unmute_encrypted_p25 = 1; opts->unmute_encrypted_p25 = 1;
} }
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
{
//may want to mute this again, or may not want to
opts->unmute_encrypted_p25 = 0;
}
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3 //only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2); state->payload_miP = (mihex1 << 32) | (mihex2);

View File

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

1275
src/ysf.c

File diff suppressed because it is too large Load Diff