mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
Compare commits
25 Commits
rtl_overha
...
2.1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f1cf0a279 | ||
|
|
5d045b89e4 | ||
|
|
a2c4679632 | ||
|
|
986ed27d7d | ||
|
|
bae6a1545e | ||
|
|
5240f00441 | ||
|
|
f7511e0976 | ||
|
|
bc27344b04 | ||
|
|
db97eb82a1 | ||
|
|
3f1b8ff736 | ||
|
|
54b9017146 | ||
|
|
8ccaf2d261 | ||
|
|
209770175d | ||
|
|
602079e681 | ||
|
|
82267b9ec8 | ||
|
|
87bf997b6e | ||
|
|
0a43d3202d | ||
|
|
ee04cef6f2 | ||
|
|
b6fdfe48c1 | ||
|
|
7a4bd2833f | ||
|
|
432ad448ba | ||
|
|
61be710bb0 | ||
|
|
3be8aacf77 | ||
|
|
4feb21cf0a | ||
|
|
7d8162ab99 |
@@ -68,6 +68,7 @@ find_package(ITPP REQUIRED)
|
||||
find_package(RTLSDR)
|
||||
find_package(Curses 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})
|
||||
set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY})
|
||||
@@ -79,6 +80,12 @@ if(RTLSDR_FOUND)
|
||||
add_definitions(-DUSE_RTLSDR)
|
||||
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 HEADERS include/*.h include/*.hpp)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Digital Speech Decoder - Florida Man Edition
|
||||
|
||||
DSD-FME is an evolution of the original DSD project from 'DSD Author' using the base code of [szechyjs](https://github.com/szechyjs/dsd "szechyjs"), some code and ideas from [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve"), [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25") and
|
||||
[Osmocom OP25](https://gitea.osmocom.org/op25/op25 "Osmocom OP25"), along with other snippets of code, information, and inspirations from other projects including [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDRTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), [OK-DMRlib](https://github.com/OK-DMR/ok-dmrlib "OK-DMRlib"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"), Eric Cottrell, SP5WWP and others. Finally, this is all brought together with original code to extend the fuctionality and add new features including NCurses Terminal and Menu system, Pulse Audio, TCP Direct Link Audio, RIGCTL, Trunking Features, LRRP/GPS Mapping, P25 Phase 2, EDACS, OP25 Capture Bin compatability, etc. DSD-FME is primarily focused with Linux Desktop users in mind, so please understand that this version may not compile, compile easily, or run correctly in other environments.
|
||||
[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.
|
||||
|
||||
|
||||
31
cmake/FindCODEC2.cmake
Normal file
31
cmake/FindCODEC2.cmake
Normal 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)
|
||||
@@ -13,7 +13,7 @@ Y='y'
|
||||
if [[ $Y == $ANSWER ]]; then
|
||||
|
||||
sudo apt update
|
||||
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev
|
||||
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 Please check to see that libitpp-dev has successfully been downloaded and installed from the repo.
|
||||
|
||||
@@ -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.
|
||||
|
||||
```
|
||||
-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
|
||||
-fa Legacy Auto (not recommended)
|
||||
-fi NXDN48
|
||||
@@ -14,6 +14,7 @@
|
||||
-f1 P25P1
|
||||
-f2 P25P2 (may need to specify wacn/sys/nac manually)
|
||||
-fx X2-TDMA
|
||||
-fy YSF
|
||||
```
|
||||
|
||||
## Conventional Frequency "Fast Scanner"
|
||||
|
||||
@@ -28,20 +28,20 @@ Debian/Mint/Ubuntu/Pi
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev
|
||||
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
|
||||
|
||||
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!!
|
||||
|
||||
@@ -74,7 +74,11 @@
|
||||
#include <locale.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
|
||||
typedef struct
|
||||
@@ -309,6 +313,9 @@ typedef struct
|
||||
int inverted_ysf;
|
||||
short int aggressive_framesync;
|
||||
|
||||
int frame_m17;
|
||||
int inverted_m17;
|
||||
|
||||
FILE *symbolfile;
|
||||
int call_alert;
|
||||
|
||||
@@ -706,14 +713,62 @@ typedef struct
|
||||
//Upsampled 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;
|
||||
|
||||
/*
|
||||
* Frame sync patterns
|
||||
*/
|
||||
|
||||
#define FUSION_SYNC "31111311313113131131" //HA!
|
||||
#define INV_FUSION_SYNC "13333133131331313313" //HA!
|
||||
//The inverse of LSF also seems to be Stream Frame Type, only going to work on Stream mode for now
|
||||
#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 P25P1_SYNC "111113113311333313133333"
|
||||
@@ -879,12 +934,15 @@ void processX2TDMAdata (dsd_opts * opts, dsd_state * state);
|
||||
void processX2TDMAvoice (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 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 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)
|
||||
short dmr_filter(short sample);
|
||||
short nxdn_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);
|
||||
uint64_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);
|
||||
|
||||
@@ -258,7 +258,6 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
||||
if( Golay_20_8_decode(SlotType) ) SlotTypeOk = 1;
|
||||
else
|
||||
{
|
||||
SlotTypeOk = -1;
|
||||
SlotTypeOk = 0;
|
||||
goto END;
|
||||
}
|
||||
|
||||
14
src/dmr_le.c
14
src/dmr_le.c
@@ -272,9 +272,15 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
|
||||
uint8_t key = (sbrc_hex >> 3) & 0xFF;
|
||||
uint8_t txi_delay = (sbrc_hex >> 3) & 0x1F; //middle five are the 'delay' value on a TXI system
|
||||
|
||||
//Note: AES-256 Key 1 will pass a CRC3 due to its bit arrangement vs the CRC poly 1101
|
||||
// if (irr_err == 0 && sbrc_hex = 0xD) crc3_okay = 0; //SB: 00000001101
|
||||
|
||||
//NOTE: on above, I belive that we need to check by opcode as well, as a CRC3 can have multiple collisions
|
||||
//so we need to exclude op/alg 0 and 3 from the check (does algID 0x03/0x23 even exist?)
|
||||
|
||||
if (opts->dmr_le == 1) //this will now require a user to switch it on or off until more testing/figuring can be done
|
||||
{
|
||||
if (irr_err != 0) fprintf (stderr, "\n %s SLOT %d SB/RC (FEC ERR) %d %s \n", KRED, slot, irr_err, KNRM);
|
||||
if (irr_err != 0) fprintf (stderr, "\n%s SLOT %d SB/RC (FEC ERR) %d %s \n", KRED, slot, irr_err, KNRM);
|
||||
if (irr_err == 0)
|
||||
{
|
||||
if (sbrc_hex == 0) ; //NULL, do nothing
|
||||
@@ -289,8 +295,8 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
|
||||
//do something with the reverse channel information
|
||||
}
|
||||
|
||||
//if the call is interruptable (TXI) and the crc3 is okay
|
||||
else if (crc3_okay == 1)
|
||||
//if the call is interruptable (TXI) and the crc3 is okay and TXI Opcode
|
||||
else if (crc3_okay == 1 && (sbrc_opcode == 0 || sbrc_opcode == 3) )
|
||||
{
|
||||
//opcodes -- 0 (NULL), BR Delay (3)
|
||||
fprintf (stderr, "\n");
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
|
||||
@@ -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) ||
|
||||
(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
|
||||
// 3 -X2-TDMA (inverted signal voice frame)
|
||||
// 5 -X2-TDMA (inverted signal data frame)
|
||||
// 9 -NXDN (inverted voice frame)
|
||||
// 9 -M17 LSR
|
||||
// 11 -DMR (inverted signal voice frame)
|
||||
// 13 -DMR (inverted signal data frame)
|
||||
// 17 -NXDN (inverted data frame)
|
||||
// 17 -M17 STR
|
||||
// 29 -NXDN (inverted FSW)
|
||||
// 31 -YSF
|
||||
// 36 -P25p2
|
||||
// 99 -M17 Preamble
|
||||
|
||||
int valid;
|
||||
int dibit;
|
||||
@@ -335,12 +338,14 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
|
||||
// 0 +P25p1
|
||||
// 2 +X2-TDMA (non inverted signal data 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)
|
||||
// 12 +DMR (non inverted signal voice frame)
|
||||
// 16 +NXDN (non inverted data frame)
|
||||
// 16 +M17 STR
|
||||
// 28 +NXND (FSW)
|
||||
// 30 +YSF
|
||||
// 35 +p25p2
|
||||
// 98 +M17 Preamble
|
||||
|
||||
int valid;
|
||||
int dibit;
|
||||
|
||||
@@ -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
|
||||
#define NZEROS 60
|
||||
float ngain = 7.423339364f;
|
||||
static float xv[NZEROS+1];
|
||||
float xcoeffs[] =
|
||||
float xcoeffs[61] =
|
||||
{ -0.0083649323f, -0.0265444850f, -0.0428141462f, -0.0537571943f,
|
||||
-0.0564141052f, -0.0489161045f, -0.0310068662f, -0.0043393881f,
|
||||
+0.0275375106f, +0.0595423283f, +0.0857543325f, +0.1003565948f,
|
||||
@@ -27,7 +55,7 @@ float xcoeffs[] =
|
||||
float nxgain = 15.95930463f;
|
||||
static float nxv[NXZEROS+1];
|
||||
|
||||
float nxcoeffs[] =
|
||||
float nxcoeffs[135] =
|
||||
{ +0.031462429f, +0.031747267f, +0.030401148f, +0.027362877f,
|
||||
+0.022653298f, +0.016379869f, +0.008737200f, +0.000003302f,
|
||||
-0.009468531f, -0.019262057f, -0.028914291f, -0.037935027f,
|
||||
@@ -74,7 +102,7 @@ const float dmrgain = 6.82973073748f;
|
||||
static float dxv[DMRNZEROS+1];
|
||||
|
||||
// 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.0404938748, -0.0528141756, -0.0543747957, -0.0428325003, -0.0186176083,
|
||||
0.0147202645, 0.0508418571, 0.0816392577, 0.0988113688, 0.0957187780,
|
||||
@@ -98,7 +126,7 @@ static float dpmrxv[NXZEROS+1];
|
||||
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
|
||||
const float dpmrcoeffs[] =
|
||||
const float dpmrcoeffs[135] =
|
||||
{-0.0000983004, 0.0058388841, 0.0119748846, 0.0179185547, 0.0232592816,
|
||||
0.0275919612, 0.0305433586, 0.0317982965, 0.0311240307,
|
||||
0.0283911865, 0.0235897433, 0.0168387650, 0.0083888763,
|
||||
@@ -156,6 +184,11 @@ dpmr_filter(short sample)
|
||||
return dsd_input_filter(sample, 4);
|
||||
}
|
||||
|
||||
short m17_filter (short sample)
|
||||
{
|
||||
return dsd_input_filter(sample, 5);
|
||||
}
|
||||
|
||||
|
||||
short
|
||||
dsd_input_filter(short sample, int mode)
|
||||
@@ -189,6 +222,14 @@ dsd_input_filter(short sample, int mode)
|
||||
coeffs = (float *)dpmrcoeffs;
|
||||
zeros = DPMRNZEROS;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
gain = m17gain;
|
||||
v = m17xv;
|
||||
coeffs = (float *)m17coeffs;
|
||||
zeros = M17ZEROS;
|
||||
break;
|
||||
|
||||
default:
|
||||
return sample;
|
||||
}
|
||||
|
||||
@@ -290,16 +290,21 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
//ysf
|
||||
else if ((state->synctype == 30) || (state->synctype == 31))
|
||||
{
|
||||
//Do stuff
|
||||
//fprintf(stderr, "YSF Sync! \n");
|
||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||
{
|
||||
//openMbeOutFile (opts, state);
|
||||
}
|
||||
//sprintf(state->fsubtype, " VOICE ");
|
||||
//relocate MBEout to inside frame handling -- Not Working Currently for YSF
|
||||
processYSF(opts, state);
|
||||
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
|
||||
else if ((state->synctype == 35) || (state->synctype == 36))
|
||||
{
|
||||
|
||||
@@ -114,16 +114,16 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
* 5 = -X2-TDMA (inverted signal data frame)
|
||||
* 6 = +D-STAR
|
||||
* 7 = -D-STAR
|
||||
* 8 = +NXDN (non inverted voice frame)
|
||||
* 9 = -NXDN (inverted voice frame)
|
||||
* 8 = +M17 STR (non inverted stream frame)
|
||||
* 9 = -M17 STR (inverted stream frame)
|
||||
* 10 = +DMR (non inverted signal data frame)
|
||||
* 11 = -DMR (inverted signal voice frame)
|
||||
* 12 = +DMR (non inverted signal voice frame)
|
||||
* 13 = -DMR (inverted signal data frame)
|
||||
* 14 = +ProVoice
|
||||
* 15 = -ProVoice
|
||||
* 16 = +NXDN (non inverted data frame)
|
||||
* 17 = -NXDN (inverted data frame)
|
||||
* 16 = +M17 LSF (non inverted link frame)
|
||||
* 17 = -M17 LSF (inverted link frame)
|
||||
* 18 = +D-STAR_HD
|
||||
* 19 = -D-STAR_HD
|
||||
* 20 = +dPMR Frame Sync 1
|
||||
@@ -215,6 +215,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
char synctest20[21]; //YSF
|
||||
char synctest21[22]; //P25 S-OEMI (SACCH)
|
||||
char synctest48[49]; //EDACS
|
||||
char synctest8[9]; //M17
|
||||
char synctest16[17]; //M17 Preamble
|
||||
char modulation[8];
|
||||
char *synctest_p;
|
||||
int symboltest_pos; //symbol test position, match to synctest_pos
|
||||
@@ -228,13 +230,21 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
t_max = 10;
|
||||
}
|
||||
//else if dPMR
|
||||
//dPMR
|
||||
else if (opts->frame_dpmr == 1)
|
||||
{
|
||||
t_max = 12; //based on Frame_Sync_2 pattern
|
||||
}
|
||||
//if Phase 2 (or YSF in future), then only 19
|
||||
else if (state->lastsynctype == 35 || state->lastsynctype == 36) //P2
|
||||
else if (opts->frame_m17 == 1)
|
||||
{
|
||||
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
|
||||
}
|
||||
@@ -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 (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;
|
||||
}
|
||||
}
|
||||
@@ -573,51 +578,138 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
}
|
||||
//YSF sync
|
||||
strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right
|
||||
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
|
||||
strncpy(synctest20, (synctest_p - 19), 20);
|
||||
if(opts->frame_ysf == 1)
|
||||
{
|
||||
if (0 == 0) //opts->inverted_ysf == 0
|
||||
if (strcmp(synctest20, FUSION_SYNC) == 0)
|
||||
{
|
||||
if (strcmp(synctest20, FUSION_SYNC) == 0)
|
||||
{
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
fprintf (stderr, "\nYSF FUSION SYNC \n");
|
||||
opts->inverted_ysf = 0; //should we set this here?
|
||||
state->lastsynctype = 30;
|
||||
if ( opts->monitor_input_audio == 1)
|
||||
{
|
||||
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
|
||||
}
|
||||
return (30);
|
||||
}
|
||||
printFrameSync (opts, state, "+YSF ", synctest_pos + 1, modulation);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
opts->inverted_ysf = 0;
|
||||
state->lastsynctype = 30;
|
||||
return (30);
|
||||
}
|
||||
}
|
||||
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
|
||||
{
|
||||
if (0 == 0) //opts->inverted_ysf == 1
|
||||
else if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
|
||||
{
|
||||
if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
|
||||
{
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
fprintf (stderr, "\nINVERTED YSF FUSION SYNC \n");
|
||||
opts->inverted_ysf = 1; //should we set this here?
|
||||
state->lastsynctype = 31;
|
||||
if ( opts->monitor_input_audio == 1)
|
||||
{
|
||||
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
|
||||
}
|
||||
return (31);
|
||||
}
|
||||
printFrameSync (opts, state, "-YSF ", synctest_pos + 1, modulation);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
opts->inverted_ysf = 1;
|
||||
state->lastsynctype = 31;
|
||||
return (31);
|
||||
}
|
||||
}
|
||||
//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
|
||||
strncpy(synctest20, (synctest_p - 19), 20);
|
||||
if(opts->frame_p25p2 == 1)
|
||||
|
||||
178
src/dsd_main.c
178
src/dsd_main.c
@@ -26,6 +26,8 @@
|
||||
#include "provoice_const.h"
|
||||
#include "git_ver.h"
|
||||
|
||||
volatile uint8_t exitflag; //fix for issue #136
|
||||
|
||||
int pretty_colors()
|
||||
{
|
||||
fprintf (stderr,"%sred\n", KRED);
|
||||
@@ -51,7 +53,7 @@ char * FM_banner[9] = {
|
||||
" ██╔══██╗██╔════╝██╔══██╗ ███║ ╚════██║",
|
||||
" ██║ ██║╚█████╗ ██║ ██║ Lima ███║ ███╔═╝",
|
||||
" ██║ ██║ ╚═══██╗██║ ██║ 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_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
|
||||
|
||||
void
|
||||
@@ -520,13 +551,15 @@ initOpts (dsd_opts * opts)
|
||||
opts->frame_dmr = 1;
|
||||
opts->frame_dpmr = 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_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
opts->uvquality = 3;
|
||||
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_m17 = 0; //samples from M17_Education seem to all be positive polarity (same from m17-tools programs)
|
||||
opts->mod_threshold = 26;
|
||||
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
|
||||
@@ -1011,6 +1044,41 @@ initState (dsd_state * state)
|
||||
sprintf (state->dpmr_caller_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
|
||||
|
||||
void
|
||||
@@ -1095,6 +1163,8 @@ usage ()
|
||||
printf (" -f2 Decode only P25 Phase 2 (6000 sps) **\n");
|
||||
printf (" -fd Decode only D-STAR\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 (" -fn Decode only NXDN96* (12.5 kHz)\n");
|
||||
printf (" -fp Decode only EDACS/ProVoice*\n");
|
||||
@@ -1104,6 +1174,7 @@ usage ()
|
||||
printf (" -xx Expect non-inverted X2-TDMA signal\n");
|
||||
printf (" -xr Expect inverted DMR signal\n");
|
||||
printf (" -xd Expect inverted ICOM dPMR signal\n");
|
||||
printf (" -xz Expect inverted M17 signal\n");
|
||||
printf ("\n");
|
||||
printf (" * denotes frame types that cannot be auto-detected.\n");
|
||||
printf (" ** Phase 2 Single Frequency may require user to manually set WACN/SYSID/CC parameters if MAC_SIGNAL not present.\n");
|
||||
@@ -1120,8 +1191,8 @@ usage ()
|
||||
printf (" (default=36)\n");
|
||||
printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n");
|
||||
printf (" (default=15)\n");
|
||||
printf (" -ma Auto-select modulation optimizations (default)\n");
|
||||
printf (" -mc Use only C4FM modulation optimizations\n");
|
||||
printf (" -ma Auto-select modulation optimizations\n");
|
||||
printf (" -mc Use only C4FM modulation optimizations (default)\n");
|
||||
printf (" -mg Use only GFSK modulation optimizations\n");
|
||||
printf (" -mq Use only 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
|
||||
cleanupAndExit (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
#ifdef USE_CODEC2
|
||||
codec2_destroy(state->codec2_1600);
|
||||
codec2_destroy(state->codec2_3200);
|
||||
#endif
|
||||
|
||||
noCarrier (opts, state);
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
@@ -1365,7 +1441,7 @@ main (int argc, char **argv)
|
||||
mbe_printVersion (versionstr);
|
||||
|
||||
#ifdef LIMAZULUTWEAKS
|
||||
fprintf (stderr," Digital Speech Decoder: LimaZulu Edition V\n");
|
||||
fprintf (stderr," Digital Speech Decoder: LimaZulu Edition VI\n");
|
||||
#else
|
||||
fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n");
|
||||
#endif
|
||||
@@ -1374,7 +1450,7 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
#ifdef AERO_BUILD
|
||||
fprintf (stderr, "Build Version: v2.1 \n");
|
||||
fprintf (stderr, "Build Version: v2.1b (20230714)\n");
|
||||
#else
|
||||
fprintf (stderr, "Build Version: %s \n", GIT_TAG);
|
||||
#endif
|
||||
@@ -1742,11 +1818,12 @@ main (int argc, char **argv)
|
||||
opts.frame_dmr = 1;
|
||||
opts.frame_dpmr = 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_out_channels = 1;
|
||||
opts.dmr_stereo = 1; //switching in 'stereo' for 'mono'
|
||||
opts.dmr_mono = 0;
|
||||
opts.dmr_stereo = 0; //switching in 'stereo' for 'mono'
|
||||
opts.dmr_mono = 1;
|
||||
state.dmr_stereo = 0;
|
||||
//opts.setmod_bw = 7000;
|
||||
sprintf (opts.output_name, "Legacy Auto");
|
||||
@@ -1763,6 +1840,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.pulse_digi_rate_out = 48000;
|
||||
opts.pulse_digi_out_channels = 1;
|
||||
opts.dmr_stereo = 0;
|
||||
@@ -1784,6 +1862,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.pulse_digi_rate_out = 48000;
|
||||
opts.pulse_digi_out_channels = 1;
|
||||
opts.dmr_stereo = 0;
|
||||
@@ -1804,6 +1883,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 1;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
state.samplesPerSymbol = 5;
|
||||
state.symbolCenter = 2;
|
||||
opts.mod_c4fm = 0;
|
||||
@@ -1835,6 +1915,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.dmr_stereo = 0;
|
||||
state.dmr_stereo = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
@@ -1864,6 +1945,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
state.samplesPerSymbol = 20;
|
||||
state.symbolCenter = 10;
|
||||
opts.mod_c4fm = 1;
|
||||
@@ -1893,8 +1975,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 1;
|
||||
state.samplesPerSymbol = 20; //10
|
||||
state.symbolCenter = 10;
|
||||
opts.frame_m17 = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0;
|
||||
@@ -1905,8 +1986,7 @@ main (int argc, char **argv)
|
||||
state.dmr_stereo = 0;
|
||||
opts.dmr_mono = 0;
|
||||
sprintf (opts.output_name, "YSF");
|
||||
fprintf (stderr,"Setting symbol rate to 2400 / second\n");
|
||||
fprintf (stderr,"Decoding only YSF frames.\nNot working yet!\n");
|
||||
fprintf (stderr,"Decoding only YSF frames. \n");
|
||||
}
|
||||
else if (optarg[0] == '2')
|
||||
{
|
||||
@@ -1920,6 +2000,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
state.samplesPerSymbol = 8;
|
||||
state.symbolCenter = 3;
|
||||
opts.mod_c4fm = 1;
|
||||
@@ -1946,6 +2027,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0;
|
||||
@@ -1971,7 +2053,8 @@ main (int argc, char **argv)
|
||||
opts.frame_dmr = 1;
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_ysf = 1;
|
||||
opts.frame_m17 = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0;
|
||||
@@ -1998,6 +2081,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0;
|
||||
@@ -2023,6 +2107,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
opts.frame_m17 = 0;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0; //
|
||||
@@ -2049,7 +2134,8 @@ main (int argc, char **argv)
|
||||
opts.frame_dmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
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.symbolCenter = 10; //same as NXDN48 - 10
|
||||
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, "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;
|
||||
//don't mess with the modulations unless you really need to
|
||||
case 'm':
|
||||
@@ -2150,20 +2262,25 @@ main (int argc, char **argv)
|
||||
break;
|
||||
case 'x':
|
||||
if (optarg[0] == 'x')
|
||||
{
|
||||
opts.inverted_x2tdma = 0;
|
||||
fprintf (stderr,"Expecting non-inverted X2-TDMA signals.\n");
|
||||
}
|
||||
{
|
||||
opts.inverted_x2tdma = 0;
|
||||
fprintf (stderr,"Expecting non-inverted X2-TDMA signals.\n");
|
||||
}
|
||||
else if (optarg[0] == 'r')
|
||||
{
|
||||
opts.inverted_dmr = 1;
|
||||
fprintf (stderr,"Expecting inverted DMR signals.\n");
|
||||
}
|
||||
{
|
||||
opts.inverted_dmr = 1;
|
||||
fprintf (stderr,"Expecting inverted DMR signals.\n");
|
||||
}
|
||||
else if (optarg[0] == 'd')
|
||||
{
|
||||
opts.inverted_dpmr = 1;
|
||||
fprintf (stderr, "Expecting inverted ICOM dPMR signals.\n");
|
||||
}
|
||||
{
|
||||
opts.inverted_dpmr = 1;
|
||||
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;
|
||||
case 'A':
|
||||
sscanf (optarg, "%i", &opts.mod_threshold);
|
||||
@@ -2363,7 +2480,8 @@ main (int argc, char **argv)
|
||||
// }
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
//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))
|
||||
{
|
||||
sprintf (opts.audio_out_dev, "%s", "/dev/dsp");
|
||||
|
||||
@@ -1058,9 +1058,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
}
|
||||
#endif
|
||||
|
||||
state->debug_audio_errors += state->errs2 + state->errs;
|
||||
|
||||
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
||||
{
|
||||
state->debug_audio_errors += state->errs2;
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
processAudio(opts, state);
|
||||
@@ -1128,9 +1129,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
}
|
||||
#endif
|
||||
|
||||
state->debug_audio_errorsR += state->errs2R + state->errsR;
|
||||
|
||||
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
||||
{
|
||||
state->debug_audio_errorsR += state->errs2R;
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
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 (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)
|
||||
{
|
||||
processAudio(opts, state);
|
||||
|
||||
@@ -85,7 +85,7 @@ char * SyncTypes[44] = {
|
||||
"NXDN",
|
||||
"NXDN",
|
||||
"YSF", //30
|
||||
"YSF",
|
||||
"YSF", //31
|
||||
"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
|
||||
#define WIDTH 36
|
||||
#define HEIGHT 23
|
||||
#define HEIGHT 25
|
||||
|
||||
int startx = 0;
|
||||
int starty = 0;
|
||||
@@ -338,7 +338,8 @@ char *choices[] = {
|
||||
"Decode dPMR",
|
||||
"Decode NXDN48",
|
||||
"Decode NXDN96",
|
||||
"Decode DMR Stereo", //was X2-TDMA*
|
||||
"Decode DMR TDMA",
|
||||
"Decode YSF FUSION",
|
||||
"Toggle Signal Inversion",
|
||||
"Key Entry",
|
||||
"Reset Call History",
|
||||
@@ -542,7 +543,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
info_win = newwin(6, WIDTH+18, starty, startx+20);
|
||||
box (info_win, 0, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -551,13 +552,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
info_win = newwin(7, WIDTH+18, starty, startx+20);
|
||||
box (info_win, 0, 0);
|
||||
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, 4, 2, " --C4FM / FSK4 only, and OP25 P2 Capture Bins");
|
||||
mvwprintw(info_win, 3, 2, " P25p1, P25p2, YSF, and DMR BS/MS");
|
||||
mvwprintw(info_win, 4, 2, " C4FM, FSK4, QPSK only (no H8D-QPSK)");
|
||||
wrefresh(info_win);
|
||||
}
|
||||
|
||||
//Input Output Options
|
||||
if (choice == 17)
|
||||
if (choice == 18)
|
||||
{
|
||||
//test making a new window while other window is open
|
||||
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
|
||||
if (choice == 13)
|
||||
if (choice == 14)
|
||||
{
|
||||
state->payload_keyid = 0;
|
||||
state->payload_keyidR = 0;
|
||||
@@ -1259,7 +1260,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dmr = 1;
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_ysf = 1;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1290,6 +1292,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 1;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 0;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 1;
|
||||
@@ -1318,6 +1321,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1356,6 +1360,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1392,7 +1397,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_nxdn96 = 0;
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_ysf = 1;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1420,6 +1426,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1447,6 +1454,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 1;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1477,6 +1485,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
//opts->unmute_encrypted_p25 = 0;
|
||||
// opts->mod_qpsk = 0;
|
||||
@@ -1504,6 +1513,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1532,6 +1542,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->frame_dpmr = 0;
|
||||
opts->frame_provoice = 0;
|
||||
opts->frame_ysf = 0;
|
||||
opts->frame_m17 = 0;
|
||||
opts->mod_c4fm = 1;
|
||||
opts->mod_qpsk = 0;
|
||||
opts->mod_gfsk = 0;
|
||||
@@ -1539,6 +1550,60 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
//opts->unmute_encrypted_p25 = 0;
|
||||
}
|
||||
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
|
||||
if (opts->inverted_dmr == 0)
|
||||
@@ -1547,6 +1612,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->inverted_dpmr = 1;
|
||||
opts->inverted_x2tdma = 1;
|
||||
opts->inverted_ysf = 1;
|
||||
opts->inverted_m17 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1554,10 +1620,11 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
opts->inverted_dpmr = 0;
|
||||
opts->inverted_x2tdma = 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++)
|
||||
{
|
||||
@@ -1582,7 +1649,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
state->lasttgR = 0;
|
||||
}
|
||||
|
||||
if (choice == 15) //toggle payload printing
|
||||
if (choice == 16) //toggle payload printing
|
||||
{
|
||||
if (opts->payload == 0)
|
||||
{
|
||||
@@ -1595,7 +1662,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, "Payload Off\n");
|
||||
}
|
||||
}
|
||||
if (choice == 16)
|
||||
if (choice == 17)
|
||||
{
|
||||
//hardset P2 WACN, SYSID, and NAC
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (choice == 19)
|
||||
if (choice == 20)
|
||||
{
|
||||
ncursesClose();
|
||||
//cleanup_rtlsdr_stream();
|
||||
@@ -1754,7 +1821,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
rtl_clean_queue();
|
||||
reset_dibit_buffer(state); //test and observe for any random issues, disable if needed
|
||||
#elif AERO_BUILD
|
||||
opts->audio_out_type = 3; //hopefully the audio stream is still/already open
|
||||
opts->audio_out_type = 5; //hopefully the audio stream is still/already open //shouldn't this be 5? Was set to 3
|
||||
#else
|
||||
opts->audio_out_type = 0; //need to see if we need to open pulseoutput as well here?
|
||||
openPulseOutput (opts);
|
||||
@@ -2158,14 +2225,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
if (opts->ncurses_compact == 1)
|
||||
{
|
||||
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");
|
||||
}
|
||||
#elif LIMAZULUTWEAKS
|
||||
if (opts->ncurses_compact == 1)
|
||||
{
|
||||
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");
|
||||
}
|
||||
#elif ZDEV_BUILD
|
||||
@@ -2194,7 +2261,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
if (i == 4) printw (" MBElib %s", versionstr);
|
||||
#ifdef 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
|
||||
if (i == 5) printw (" %s ", "zDEV Build");
|
||||
if (i == 6) printw (" %s \n", GIT_TAG);
|
||||
@@ -2352,7 +2419,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
printw ("| Fast Scan Mode Enabled ");
|
||||
if (state->lcn_freq_roll != 0)
|
||||
printw (" - Frequency: [%.06lf] Mhz", (double)state->trunk_lcn_freq[state->lcn_freq_roll-1]/1000000);
|
||||
printw (" - 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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
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 (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)
|
||||
@@ -2433,7 +2630,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
if (idas == 1) printw ("Monitoring RTCH2 Channel"); //Idas RTCH2
|
||||
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 ("| ");
|
||||
#ifdef LIMAZULUTWEAKS
|
||||
// #ifdef LIMAZULUTWEAKS
|
||||
if (idas == 0) printw ("NXDN - RAN: [%02d] ", state->nxdn_last_ran);
|
||||
if (idas == 1) printw ("IDAS - Area: [%02d] ", state->nxdn_last_ran);
|
||||
#else
|
||||
if (idas == 0) printw ("NXDN - RAN: [%02d] ", rn);
|
||||
if (idas == 1) printw ("IDAS - Area: [%02d] ", rn);
|
||||
#endif
|
||||
// #else
|
||||
// if (idas == 0) printw ("NXDN - RAN: [%02d] ", rn);
|
||||
// if (idas == 1) printw ("IDAS - Area: [%02d] ", rn);
|
||||
// #endif
|
||||
if (state->nxdn_location_site_code != 0)
|
||||
{
|
||||
printw ("Cat: [%s] ", state->nxdn_location_category);
|
||||
@@ -2581,15 +2778,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
printw ("%s", state->dmr_site_parms); //site id, net id, etc
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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
|
||||
@@ -2624,7 +2821,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
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");
|
||||
attron(COLOR_PAIR(3));
|
||||
}
|
||||
if (state->payload_algid == 0x83 || state->payload_algid == 0x23)
|
||||
if (state->payload_algid == 0x83)
|
||||
{
|
||||
attron(COLOR_PAIR(1));
|
||||
printw("Triple DES");
|
||||
@@ -2914,7 +3111,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
printw("DES-OFB");
|
||||
attron(COLOR_PAIR(3));
|
||||
}
|
||||
if (state->payload_algidR == 0x83 || state->payload_algidR == 0x23)
|
||||
if (state->payload_algidR == 0x83)
|
||||
{
|
||||
attron(COLOR_PAIR(1));
|
||||
printw("Triple DES");
|
||||
@@ -3049,7 +3246,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
if (state->p25_vc_freq[0] != 0)
|
||||
{
|
||||
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));
|
||||
else attroff(COLOR_PAIR(4));
|
||||
@@ -3363,6 +3560,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
opts->inverted_dpmr = 1;
|
||||
opts->inverted_x2tdma = 1;
|
||||
opts->inverted_ysf = 1;
|
||||
opts->inverted_m17 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3370,6 +3568,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
opts->inverted_dpmr = 0;
|
||||
opts->inverted_x2tdma = 0;
|
||||
opts->inverted_ysf = 0;
|
||||
opts->inverted_m17 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
{
|
||||
|
||||
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
|
||||
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 ( (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);
|
||||
}
|
||||
|
||||
else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||
|
||||
state->lastsynctype == 16 || state->lastsynctype == 17 ||
|
||||
else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||state->lastsynctype == 16 || state->lastsynctype == 17)
|
||||
{
|
||||
sample = m17_filter(sample);
|
||||
}
|
||||
|
||||
else if (
|
||||
state->lastsynctype == 20 || state->lastsynctype == 21 ||
|
||||
state->lastsynctype == 22 || state->lastsynctype == 23 ||
|
||||
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
|
||||
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
|
||||
if (opts->audio_out_type == 0 && opts->use_ncurses_terminal == 1)
|
||||
{
|
||||
|
||||
746
src/m17.c
Normal file
746
src/m17.c
Normal 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
|
||||
@@ -36,13 +36,13 @@
|
||||
|
||||
|
||||
/* 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 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_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
|
||||
static const uint8_t CNXDNConvolution_BRANCH_TABLE1[8] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
|
||||
static const uint8_t CNXDNConvolution_BRANCH_TABLE2[8] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
|
||||
|
||||
static const unsigned int CNXDNConvolution_NUM_OF_STATES_D2 = 8U;
|
||||
static const unsigned int CNXDNConvolution_NUM_OF_STATES = 16U;
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "dsd.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,
|
||||
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,
|
||||
@@ -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
|
||||
};
|
||||
|
||||
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
|
||||
void nxdn_descramble(uint8_t dibits[], int len)
|
||||
|
||||
@@ -144,6 +144,10 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
|
||||
NXDN_decode_VCALL(opts, state, ElementsContent);
|
||||
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
|
||||
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
|
||||
{
|
||||
@@ -174,7 +178,8 @@ 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
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
break;
|
||||
|
||||
//Idle
|
||||
|
||||
@@ -469,7 +469,7 @@ processHDU(dsd_opts* opts, dsd_state* state)
|
||||
{
|
||||
|
||||
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_keyid = kidhex;
|
||||
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);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
|
||||
{
|
||||
//may want to mute this again, or may not want to
|
||||
opts->unmute_encrypted_p25 = 0;
|
||||
}
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
|
||||
state->payload_miP = (mihex1 << 32) | (mihex2);
|
||||
|
||||
@@ -371,7 +371,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
if (irrecoverable_errors == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%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_keyid = kidhex;
|
||||
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);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
|
||||
{
|
||||
//may want to mute this again, or may not want to
|
||||
opts->unmute_encrypted_p25 = 0;
|
||||
}
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
|
||||
state->payload_miP = (mihex1 << 32) | (mihex2);
|
||||
|
||||
@@ -223,7 +223,6 @@ unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tr
|
||||
void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits)
|
||||
{
|
||||
int n;
|
||||
signed char dibit;
|
||||
//can only assume this is giving the correct dibits out, and not inverse or something.
|
||||
/*
|
||||
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 reverse_points[49U];
|
||||
// unsigned char reverse_points[49U];
|
||||
CDMRTrellisDibitsToPoints(dibits, points);
|
||||
//maybe keep point 49 at 49, since its the flush?
|
||||
//fprintf (stderr, "\n Trellis Reverse Points inside Decoder\n ");
|
||||
for (short i = 0; i < 49; i++)
|
||||
{
|
||||
reverse_points[i] = points[48-i];
|
||||
//fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]);
|
||||
}
|
||||
// for (short i = 0; i < 49; i++)
|
||||
// {
|
||||
// reverse_points[i] = points[48-i];
|
||||
// //fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]);
|
||||
// }
|
||||
//reverse_points[48] = points[48];
|
||||
//fprintf (stderr, "#%d [%02u] ", 48, reverse_points[48]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user