mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 17:27:21 -05:00
@@ -14,7 +14,7 @@ find_package(MBE REQUIRED)
|
||||
find_package(ITPP REQUIRED)
|
||||
find_package(RTLSDR)
|
||||
find_package(Curses REQUIRED)
|
||||
find_package(PULSEAUDIO)
|
||||
find_package(PULSEAUDIO REQUIRED)
|
||||
|
||||
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})
|
||||
|
||||
58
README.md
58
README.md
@@ -1,26 +1,34 @@
|
||||
# Digital Speech Decoder - Florida Man Edition
|
||||
|
||||

|
||||
# Digital Speech Decoder - Florida Man Edition
|
||||
|
||||
This version of DSD is a flavor blend of [szechyjs](https://github.com/szechyjs/dsd "szechyjs") RTL branch and some of my own additions, along with portions of DMR and NXDN code from the [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve") branch as well. This code also borrows snippets, inspiration, and ideas from other open source works including [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25"), [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), and [LFSR](https://github.com/mattames/LFSR "LFSR"). 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 and hrh17 for the many hours of wav samples submitted by them.
|
||||
|
||||
## 2022.06.20 Update - Current Users Please Read!! ##
|
||||
The executable for this project has been changed from `dsd` to `dsd-fme` so after pulling or cloning the lastest version, make sure to call the software with `dsd-fme`. It may also be beneficial to open your current build folder and run `sudo make uninstall` to uninstall the binary named `dsd` or to run `sudo rm /usr/local/bin/dsd` to alleviate any confusion or from accidentally calling the older version as it will still be installed along with the new `dsd-fme` executable. The Summer Cleanup Project has also seen a lot of the files that weren't in use, or used for github workflows and cmake files removed from the project folder, slimming it down quite considerably. If you have any issue doing a git pull to get the current version, you may need to instead do a fresh clone, build, and install in a clean folder. Check the info below about running download-and-install-nodeps.sh if needed.
|
||||
## 2022.08.12 Update ##
|
||||
A new menu system has been introduced in the NCURSES Terminal. While running DSD-FME, a user can simply use the ESC or arrow keys to open the menu and change options on the fly. This is extremely beneficial when wanting to change settings on the fly, and also to alleviate the need to use complex start up command line arguments. All of the previous command line arguments still work and will get you up faster, but if you would rather configure after start up, or change settings while running, the menu system is very helpful in that regard.
|
||||
|
||||
## 2022.05.05 Update ##
|
||||
I have successfully added a DMR Stereo method for listening to voice audio in both TDMA channels/slots simultaneously. This method will also allow for data decoding in the opposite slot if only one voice call is active, allowing the user not to miss any useful information in the second slot while the previous slot is in use. DMR Stereo also has vastly improved handling of MS/Simplex voice decoding and (hit or miss) MS data decoding. To call this method, see the example below. The old method of decoding DMR is also included and is stil the default for the time being, but the DMR Stereo method is working well, users are encouraged to try both methods and find the one that is suitable for them. New commands include:
|
||||
```
|
||||
-T Enable DMR 'TDMA' Stereo
|
||||
-F Enable Passive Frame Sync
|
||||
```
|
||||
Please note, for the time being, MBE file saving and WAV file saving are disabled while using DMR Stereo. These features are still present in the default DMR handling and other voice decoder options and will be re-integrated into DMR Stereo in the future. DMR Stereo will also need to be enabled to handle DMR MS/Simplex voice, as it was removed from the default method due to poor performance.
|
||||
[](https://www.youtube.com/watch?v=TqTfAfaPJ4s "DSD-FME Update 2022.08.12")
|
||||
|
||||
Use Passive Frame Sync if voice in both slots becomes choppy or skips. Using Passive Sync may cause wonky audio though, depends on quality of signal and bit errors present.
|
||||
To get started with the new menu system, simply launch with:
|
||||
|
||||
`dsd-fme -N 2> log.txt`
|
||||
|
||||
Virtually all the examples listed below can now be set up on the fly with the menu system, no need to check the help or refer to this page.
|
||||
|
||||
This release also has provisional support for playing back OP25 capture bin files, and the creation and playback of its own capture bin files as well (most likely not OP25 compatible). Mileage may vary. Be sure to choose the decoder option required when playing a bin file back, do not rely on auto-detect. Capture Bin files can be used to reliably replay P25, DMR BS, and NXDN decodings, and can replace the need for MBE file saving in the case of DMR Stereo, allowing for a complete replay of all events on a system, rather than just voice only.
|
||||
|
||||
Per Call wav file creation has been implemented, currently only for DMR Stereo. Complete audio decode wav is available for all other decoder types. LRRP has been revamped, working more consistently, and an option to dump LRRP data to ~/lrrp.txt in the user home directory now exists, and can be imported into open-source QGIS to provide mapping data for LRRP output. Simply open the newly included map file in QGIS and point it at your geographic region. (Be sure the lrrp.txt file exists, and has data populated in it prior to opening the map file in QGIS, otherwise, the map layer may not want to show back up!)
|
||||
|
||||
DMR Data Header decoding has been revamped, and most data burst decoding types tightened up and code cleaned. FEC error checking now implemented on CACH and Burst types, cleaning up some erroneous slot and burst errors.
|
||||
|
||||
## 2022.06.20 Update - Current Users Please Read!! ##
|
||||
The executable for this project has been changed from `dsd` to `dsd-fme` so after pulling or cloning the lastest version, make sure to call the software with `dsd-fme`.
|
||||
|
||||
## 2022.05.05 Update ##
|
||||
DMR Stereo method added for listening to voice audio in both TDMA channels/slots simultaneously.
|
||||
|
||||
### Example Usage and Note!
|
||||
`dsd-fme` or `./dsd-fme` may need to be used in your usage, depending on if you are running it from the build folder, or if you have run make install. You will need to tweak the examples to your particular usage. Users can always check `dsd-fme -h` for help and all command line switches to use.
|
||||
|
||||
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR, P25P1, D-STAR, and X2-TDMA decoding. To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed.
|
||||
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR, P25P1, D-STAR, and X2-TDMA decoding. 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.
|
||||
|
||||
```
|
||||
-fi NXDN48
|
||||
@@ -39,8 +47,6 @@ and in a second terminal tab, same folder, run
|
||||
|
||||
`tail -n 40 -f voice.log`
|
||||
|
||||

|
||||
|
||||
Then you can open up your pavucontrol "Pulse Audio Volume Control" or "Volume Control" application and route input into DSD-FME from any application and DSD-FME output to the left and right speakers respectively. (unlock the channel in the application stream and adjust left and right independently)
|
||||
|
||||
## Example Usage - RTL2832 Dongle Input
|
||||
@@ -79,24 +85,27 @@ and in a second terminal tab, same folder, run
|
||||
|
||||
`tail -n 40 -f voice.log`
|
||||
|
||||

|
||||
|
||||
## Roadmap
|
||||
The Current list of objectives include:
|
||||
|
||||
1. ~~Random Tinkering~~ More Random Tinkering
|
||||
1. Include P25 P2 Audio decoding with capture bin files, then RTL input and/or disc tap input.
|
||||
~~Random Tinkering~~ ~~More Random Tinkering~~
|
||||
|
||||
2. ~~Implemented Pulse Audio~~ Remove remaining PortAudio code, ~~improved Pulse Audio for stereo output and channel/slot separation~~ and reimplement wav file saving using DMR Stereo method for stereo wav files, or seperate as per call wav files.
|
||||
2. ~~Implemented Pulse Audio~~ ~~Remove remaining PortAudio code,~~ ~~improved Pulse Audio for stereo output and channel/slot separation~~ ~~and reimplement wav file saving using DMR Stereo method for stereo wav files, or seperate as per call wav files.~~
|
||||
|
||||
3. ~~Improve NXDN and DMR support~~ Continue to improve ~~NXDN and DMR~~ all data and voice decoding.
|
||||
3. ~~Improve NXDN and DMR support~~ Continue to improve ~~NXDN and DMR~~ all data and voice decoding.
|
||||
|
||||
4. ~~More Concise Printouts - Ncurses~~
|
||||
|
||||
5. ~~Make simple to use installer script.~~
|
||||
5. ~~Make simple to use installer script.~~
|
||||
|
||||
## How to clone, check out, and build this branch
|
||||
|
||||
### Ubuntu 22.04/20.04/LM20/Debian Bullseye or Newer:
|
||||
|
||||
Using the included download-and-install.sh should make for a simple and painless clone, build, and install on newer Debian/Ubuntu/Mint/Pi systems. Simply acquire or copy the script, and run it. Update: Ubuntu 22.04 and RPi Bullseye 64-bit has been tested working with the installer script and functions appropriately.
|
||||
Using the included download-and-install.sh should make for a simple and painless clone, build, and install on newer Debian/Ubuntu/Mint/Pi systems. Simply acquire or copy the script, and run it. Update: Ubuntu 22.04 and RPi Bullseye 64-bit has been tested working with the installer script and functions appropriately.
|
||||
|
||||
If you need all dependencies build and installed first (only on Debian/Ubuntu/Mint/Pi), run:
|
||||
|
||||
@@ -119,7 +128,7 @@ The above install.sh should now function on older system types. You can elect to
|
||||
|
||||
## Manual Install
|
||||
|
||||
First, install dependency packages. This guide will assume you are using Debian/Ubuntu based distros. Check your package manager for equivalent packages if different.
|
||||
First, install dependency packages. This guide will assume you are using Debian/Ubuntu based distros. Check your package manager for equivalent packages if different.
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
@@ -139,7 +148,7 @@ sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat l
|
||||
wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
|
||||
tar xjf itpp*
|
||||
#if you can't cd into this folder, double check folder name first
|
||||
cd itpp-4.3.1
|
||||
cd itpp-4.3.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
@@ -199,7 +208,6 @@ Already have this branch, and just want to pull the latest build? You can run th
|
||||
git pull https://github.com/lwvmobile/dsd-fme pulseaudio
|
||||
##cd into your build folder##
|
||||
cd build
|
||||
##cmake usually isn't necesary, but could be if I update the cmakelist.txt
|
||||
cmake ..
|
||||
make -j `nproc`
|
||||
sudo make install
|
||||
@@ -225,5 +233,3 @@ GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
|
||||
BIN
dsd-fme-qgis-map.qgz
Normal file
BIN
dsd-fme-qgis-map.qgz
Normal file
Binary file not shown.
BIN
dsd-fme.png
BIN
dsd-fme.png
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 212 KiB |
BIN
dsd-fme2.png
BIN
dsd-fme2.png
Binary file not shown.
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 153 KiB |
182
include/dsd.h
182
include/dsd.h
@@ -40,12 +40,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef SOLARIS
|
||||
#include <sys/audioio.h>
|
||||
#endif
|
||||
#if defined(BSD) && !defined(__APPLE__)
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <mbelib.h>
|
||||
#include <sndfile.h>
|
||||
@@ -54,29 +49,16 @@
|
||||
|
||||
#include <pulse/simple.h> //PULSE AUDIO
|
||||
#include <pulse/error.h> //PULSE AUDIO
|
||||
//#include <pulse/pulseaudio.h> //PUlSE AUDIO
|
||||
|
||||
#define SAMPLE_RATE_IN 48000 //48000
|
||||
#define SAMPLE_RATE_OUT 8000 //8000,
|
||||
|
||||
#ifdef USE_PORTAUDIO
|
||||
#include "portaudio.h"
|
||||
#define PA_FRAMES_PER_BUFFER 64
|
||||
//Buffer needs to be large enough to prevent input buffer overruns while DSD is doing other struff (like outputting voice)
|
||||
//else you get skipped samples which result in incomplete/erronous decodes and a mountain of error messages.
|
||||
#define PA_LATENCY_IN 0.500
|
||||
//Buffer needs to be large enough to prevent output buffer underruns while DSD is doing other stuff (like decoding input)
|
||||
//else you get choppy audio and in 'extreme' cases errors.
|
||||
//Buffer also needs to be as small as possible so we don't have a lot of audio delay.
|
||||
#define PA_LATENCY_OUT 0.100
|
||||
#endif
|
||||
|
||||
#ifdef USE_RTLSDR
|
||||
#include <rtl-sdr.h>
|
||||
#endif
|
||||
//look into making this not required by doing ifdef, make new c file for methods, and CLI case option for ncurses terminal
|
||||
#include <locale.h> //move this stuff to dsd.h
|
||||
#include <ncurses.h> //move this stuff to dsd.h
|
||||
|
||||
#include <locale.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
static volatile int exitflag;
|
||||
|
||||
@@ -153,18 +135,6 @@ typedef struct
|
||||
uint8_t NextIVComputed[8];
|
||||
} NxdnElementsContent_t;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MODE_UNENCRYPTED,
|
||||
MODE_BASIC_PRIVACY,
|
||||
MODE_ENHANCED_PRIVACY_ARC4,
|
||||
MODE_ENHANCED_PRIVACY_AES256,
|
||||
MODE_HYTERA_BASIC_40_BIT,
|
||||
MODE_HYTERA_BASIC_128_BIT,
|
||||
MODE_HYTERA_BASIC_256_BIT
|
||||
};
|
||||
|
||||
//Read Solomon (12,9) constant
|
||||
#define RS_12_9_DATASIZE 9
|
||||
#define RS_12_9_CHECKSUMSIZE 3
|
||||
@@ -281,20 +251,16 @@ typedef struct
|
||||
int audio_in_fd;
|
||||
SNDFILE *audio_in_file;
|
||||
SF_INFO *audio_in_file_info;
|
||||
#ifdef USE_PORTAUDIO
|
||||
PaStream* audio_in_pa_stream;
|
||||
#endif
|
||||
|
||||
uint32_t rtlsdr_center_freq;
|
||||
int rtlsdr_ppm_error; //was int, changed to float
|
||||
int audio_in_type; // 0 for device, 1 for file, 2 for portaudio, 3 for rtlsdr
|
||||
int audio_in_type; // 0 for device, 1 for file, 3 for rtlsdr
|
||||
char audio_out_dev[1024];
|
||||
int audio_out_fd;
|
||||
SNDFILE *audio_out_file;
|
||||
SF_INFO *audio_out_file_info;
|
||||
#ifdef USE_PORTAUDIO
|
||||
PaStream* audio_out_pa_stream;
|
||||
#endif
|
||||
int audio_out_type; // 0 for device, 1 for file, 2 for portaudio
|
||||
|
||||
int audio_out_type; // 0 for device, 1 for file,
|
||||
int split;
|
||||
int playoffset;
|
||||
int playoffsetR;
|
||||
@@ -302,11 +268,19 @@ typedef struct
|
||||
char mbe_out_file[1024];
|
||||
char mbe_out_path[1024];
|
||||
FILE *mbe_out_f;
|
||||
FILE *symbol_out_f;
|
||||
float audio_gain;
|
||||
float audio_gainR;
|
||||
int audio_out;
|
||||
int dmr_stereo_wav;
|
||||
char wav_out_file[1024];
|
||||
char wav_out_fileR[1024];
|
||||
char wav_out_file_raw[1024];
|
||||
char symbol_out_file[1024];
|
||||
short int symbol_out;
|
||||
SNDFILE *wav_out_f;
|
||||
SNDFILE *wav_out_fR;
|
||||
SNDFILE *wav_out_raw;
|
||||
//int wav_out_fd;
|
||||
int serial_baud;
|
||||
char serial_dev[1024];
|
||||
@@ -315,6 +289,7 @@ typedef struct
|
||||
int frame_dstar;
|
||||
int frame_x2tdma;
|
||||
int frame_p25p1;
|
||||
int frame_p25p2;
|
||||
int frame_nxdn48;
|
||||
int frame_nxdn96;
|
||||
int frame_dmr;
|
||||
@@ -338,17 +313,16 @@ typedef struct
|
||||
int rtl_volume_multiplier;
|
||||
int rtl_udp_port;
|
||||
int rtl_bandwidth;
|
||||
int rtl_started;
|
||||
int monitor_input_audio;
|
||||
int pulse_raw_rate_in;
|
||||
int pulse_raw_rate_out;
|
||||
int pulse_digi_rate_in;
|
||||
int pulse_digi_rate_out;
|
||||
//int pulse_digi_rate_outR;
|
||||
int pulse_raw_in_channels;
|
||||
int pulse_raw_out_channels;
|
||||
int pulse_digi_in_channels;
|
||||
int pulse_digi_out_channels;
|
||||
//int pulse_digi_out_channelsR;
|
||||
int pulse_flush;
|
||||
pa_simple *pulse_raw_dev_in;
|
||||
pa_simple *pulse_raw_dev_out;
|
||||
@@ -356,23 +330,28 @@ typedef struct
|
||||
pa_simple *pulse_digi_dev_out;
|
||||
pa_simple *pulse_digi_dev_outR;
|
||||
int use_ncurses_terminal;
|
||||
int ncurses_compact;
|
||||
int ncurses_history;
|
||||
int reset_state;
|
||||
int payload;
|
||||
char output_name[1024];
|
||||
|
||||
int EncryptionMode;
|
||||
|
||||
unsigned int dPMR_curr_frame_is_encrypted;
|
||||
int dPMR_next_part_of_superframe;
|
||||
int inverted_dpmr;
|
||||
int frame_dpmr;
|
||||
//
|
||||
short int dmr_stereo;
|
||||
|
||||
//
|
||||
short int dmr_stereo;
|
||||
short int lrrp_file_output;
|
||||
|
||||
short int dmr_mute_encL;
|
||||
short int dmr_mute_encR;
|
||||
|
||||
int frame_ysf;
|
||||
int inverted_ysf; //not sure if ysf comes in inverted or not, but signal could if IQ flipped
|
||||
short int aggressive_framesync; //set to 1 for more aggressive framesync, 0 for less aggressive
|
||||
int inverted_ysf;
|
||||
short int aggressive_framesync;
|
||||
|
||||
FILE *symbolfile;
|
||||
|
||||
} dsd_opts;
|
||||
|
||||
@@ -380,8 +359,8 @@ typedef struct
|
||||
{
|
||||
int *dibit_buf;
|
||||
int *dibit_buf_p;
|
||||
int *dmr_payload_buf; //try loading up a small amount to buffer, 144 or 288?
|
||||
int *dmr_payload_p; //position for payload buffer
|
||||
int *dmr_payload_buf;
|
||||
int *dmr_payload_p;
|
||||
int repeat;
|
||||
short *audio_out_buf;
|
||||
short *audio_out_buf_p;
|
||||
@@ -415,13 +394,15 @@ typedef struct
|
||||
int maxbuf[1024];
|
||||
int minbuf[1024];
|
||||
int midx;
|
||||
char err_str[64]; //actual error errorbars
|
||||
char err_buf[64]; //make copy of err_str for comparison, only have string print when strcmp is different??
|
||||
char err_str[64];
|
||||
char err_buf[64];
|
||||
char err_strR[64];
|
||||
char err_bufR[64];
|
||||
char fsubtype[16];
|
||||
char ftype[16];
|
||||
int symbolcnt;
|
||||
int symbolc;
|
||||
|
||||
int rf_mod;
|
||||
int numflips;
|
||||
int lastsynctype;
|
||||
@@ -473,12 +454,12 @@ typedef struct
|
||||
int payload_mfid;
|
||||
int payload_mfidR;
|
||||
int payload_mi;
|
||||
int payload_miR; //check to see if anything tied to this still functions appropriately
|
||||
uint64_t payload_miP;
|
||||
int payload_lsfr;
|
||||
int payload_lsfrR;
|
||||
int payload_miR;
|
||||
unsigned long long int payload_miN;
|
||||
unsigned long long int payload_miP;
|
||||
int p25vc;
|
||||
unsigned long long int K;
|
||||
int M;
|
||||
int menuopen;
|
||||
|
||||
unsigned int debug_audio_errors;
|
||||
unsigned int debug_audio_errorsR;
|
||||
@@ -506,7 +487,8 @@ typedef struct
|
||||
unsigned int nxdn_key;
|
||||
char nxdn_call_type[1024];
|
||||
char dmr_callsign[2][6][99]; //plenty of room in case of overflow;
|
||||
char dmr_lrrp[2][6][9999];
|
||||
char dmr_lrrp[2][6][9999]; //memory hog
|
||||
unsigned long long int dmr_lrrp_source[2];
|
||||
|
||||
NxdnSacchRawPart_t NxdnSacchRawPart[4];
|
||||
NxdnFacch1RawPart_t NxdnFacch1RawPart[2];
|
||||
@@ -539,16 +521,21 @@ typedef struct
|
||||
TimeSlotVoiceSuperFrame_t TS2SuperFrame;
|
||||
|
||||
char dmr_branding[25];
|
||||
uint8_t dmr_12_rate_sf[2][60]; //going five frames deep by 12 bytes //[slot][value]
|
||||
uint8_t dmr_34_rate_sf[2][64]; //going four frames deep by 16 bytes //[slot][value]
|
||||
int dmr_stereo_payload[144]; //load up 144 dibit buffer for every single DMR TDMA frame
|
||||
//uint8_t dmr_stereo_payload[144]; //load up 144 dibit buffer for every single DMR TDMA frame
|
||||
uint8_t dmr_12_rate_sf[2][288]; //was 84, expanded to 288 to prevent possible crash if more comes in than expected
|
||||
uint8_t dmr_34_rate_sf[2][288]; //was 96, expanded to 288 to prevent possible crash if more comes in than expected
|
||||
int dmr_stereo_payload[144]; //load up 144 dibit buffer for every single DMR TDMA frame
|
||||
uint8_t data_header_blocks[2]; //collect number of blocks to follow from data header per slot
|
||||
uint8_t data_header_padding[2]; //collect number of padding octets in last block per slot
|
||||
uint8_t data_header_format[2]; //collect format of data header (conf or unconf) per slot
|
||||
uint8_t data_header_sap[2]; //collect sap info per slot
|
||||
uint8_t data_block_counter[2]; //counter for number of data blocks collected
|
||||
uint8_t data_p_head[2]; //flag for dmr proprietary header to follow
|
||||
|
||||
|
||||
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
|
||||
|
||||
//These flags are used to known the DMR frame
|
||||
//printing format (hex or binary)
|
||||
//printing format (hex or binary)
|
||||
int printDMRRawVoiceFrameHex;
|
||||
int printDMRRawVoiceFrameBin;
|
||||
int printDMRRawDataFrameHex;
|
||||
@@ -557,7 +544,7 @@ typedef struct
|
||||
int printDMRAmbeVoiceSampleBin;
|
||||
|
||||
//These flags are used to known the dPMR frame
|
||||
//orinting format (hex or binary)
|
||||
//orinting format (hex or binary)
|
||||
int printdPMRRawVoiceFrameHex;
|
||||
int printdPMRRawVoiceFrameBin;
|
||||
int printdPMRRawDataFrameHex;
|
||||
@@ -574,10 +561,11 @@ typedef struct
|
||||
short int dmr_ms_mode;
|
||||
unsigned int dmrburstL;
|
||||
unsigned int dmrburstR;
|
||||
int dropL;
|
||||
int dropR;
|
||||
unsigned long long int R;
|
||||
|
||||
// int block_count;
|
||||
short int dmr_encL;
|
||||
short int dmr_encR;
|
||||
|
||||
//dstar header for ncurses
|
||||
unsigned char dstarradioheader[41];
|
||||
|
||||
@@ -604,6 +592,21 @@ typedef struct
|
||||
#define INV_P25P1_SYNC "333331331133111131311111"
|
||||
#define P25P1_SYNC "111113113311333313133333"
|
||||
|
||||
//preliminary P2 sync
|
||||
|
||||
// static const uint64_t P25P2_FRAME_SYNC_MAGIC = 0x575D57F7FFLL; // 40 bits
|
||||
// static const uint64_t P25P2_FRAME_SYNC_REV_P = 0x575D57F7FFLL ^ 0xAAAAAAAAAALL;
|
||||
#define P25P2_SYNC "11131131111333133333"
|
||||
#define INV_P25P2_SYNC "33313313333111311111"
|
||||
// static const uint64_t P25P2_FRAME_SYNC_MASK = 0xFFFFFFFFFFLL; //wonder what the mask was for if its all F
|
||||
//
|
||||
// static const uint64_t P25P2_FRAME_SYNC_N1200 = 0x0104015155LL;
|
||||
//#define P25P2_SYNC_N ""
|
||||
// static const uint64_t P25P2_FRAME_SYNC_X2400 = 0xa8a2a8d800LL;
|
||||
//#define P25P2_SYNC_X ""
|
||||
// static const uint64_t P25P2_FRAME_SYNC_P1200 = 0xfefbfeaeaaLL;
|
||||
//#define P25P2_SYNC_P ""
|
||||
|
||||
#define X2TDMA_BS_VOICE_SYNC "113131333331313331113311"
|
||||
#define X2TDMA_BS_DATA_SYNC "331313111113131113331133"
|
||||
#define X2TDMA_MS_DATA_SYNC "313113333111111133333313"
|
||||
@@ -628,9 +631,8 @@ typedef struct
|
||||
#define DMR_MS_DATA_SYNC "311131133313133331131113"
|
||||
#define DMR_MS_VOICE_SYNC "133313311131311113313331"
|
||||
|
||||
//inversion testing on MS
|
||||
//#define DMR_MS_DATA_SYNC "133313311131311113313331"
|
||||
//#define DMR_MS_VOICE_SYNC "311131133313133331131113"
|
||||
//Testing NXDN FSW again
|
||||
#define NXDN_FSW "3131331131"
|
||||
|
||||
#define DMR_RC_DATA_SYNC "131331111133133133311313"
|
||||
|
||||
@@ -670,7 +672,10 @@ void processAudio (dsd_opts * opts, dsd_state * state);
|
||||
void processAudioR (dsd_opts * opts, dsd_state * state);
|
||||
void openPulseInput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet
|
||||
void openPulseOutput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet
|
||||
void closePulseInput (dsd_opts * opts);
|
||||
void closePulseOutput (dsd_opts * opts);
|
||||
void writeSynthesizedVoice (dsd_opts * opts, dsd_state * state);
|
||||
void writeSynthesizedVoiceR (dsd_opts * opts, dsd_state * state);
|
||||
void playSynthesizedVoice (dsd_opts * opts, dsd_state * state);
|
||||
void playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state);
|
||||
void openAudioOutDevice (dsd_opts * opts, int speed);
|
||||
@@ -690,7 +695,17 @@ void openMbeInFile (dsd_opts * opts, dsd_state * state);
|
||||
void closeMbeOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void openMbeOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void openWavOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void openWavOutFileL (dsd_opts * opts, dsd_state * state);
|
||||
void openWavOutFileR (dsd_opts * opts, dsd_state * state);
|
||||
void openWavOutFileRaw (dsd_opts * opts, dsd_state * state);
|
||||
void openSymbolOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void closeSymbolOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void writeSymbolOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void writeRawSample (dsd_opts * opts, dsd_state * state, short sample);
|
||||
void closeWavOutFile (dsd_opts * opts, dsd_state * state);
|
||||
void closeWavOutFileL (dsd_opts * opts, dsd_state * state);
|
||||
void closeWavOutFileR (dsd_opts * opts, dsd_state * state);
|
||||
void closeWavOutFileRaw (dsd_opts * opts, dsd_state * state);
|
||||
void printFrameInfo (dsd_opts * opts, dsd_state * state);
|
||||
void processFrame (dsd_opts * opts, dsd_state * state);
|
||||
void printFrameSync (dsd_opts * opts, dsd_state * state, char *frametype, int offset, char *modulation);
|
||||
@@ -724,22 +739,20 @@ 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 processP2(dsd_opts * opts, dsd_state * state); //P2
|
||||
short dmr_filter(short sample);
|
||||
short nxdn_filter(short sample);
|
||||
|
||||
|
||||
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr);
|
||||
/* Global functions */ //also borrowed
|
||||
uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength);
|
||||
uint32_t ConvertAsciiToByte(uint8_t AsciiMsbByte, uint8_t AsciiLsbByte, uint8_t * OutputByte);
|
||||
void Convert49BitSampleInto7Bytes(char * InputBit, char * OutputByte);
|
||||
void Convert7BytesInto49BitSample(char * InputByte, char * OutputBit);
|
||||
//
|
||||
//ifdef ncurses
|
||||
void ncursesOpen ();
|
||||
|
||||
void ncursesOpen (dsd_opts * opts, dsd_state * state);
|
||||
void ncursesPrinter (dsd_opts * opts, dsd_state * state);
|
||||
void ncursesClose ();
|
||||
//endif ncurses
|
||||
|
||||
/* NXDN frame decoding functions */
|
||||
void ProcessNXDNFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted);
|
||||
@@ -763,7 +776,7 @@ uint8_t NXDN_decode_LICH(uint8_t InputLich[8],
|
||||
uint8_t * Option,
|
||||
uint8_t * Direction,
|
||||
uint8_t * CompleteLichBinaryFormat,
|
||||
uint8_t Inverted);
|
||||
uint8_t Inverted);
|
||||
uint8_t NXDN_SACCH_raw_part_decode(uint8_t * Input, uint8_t * Output);
|
||||
void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state);
|
||||
uint8_t NXDN_FACCH1_decode(uint8_t * Input, uint8_t * Output);
|
||||
@@ -778,12 +791,11 @@ char * NXDN_Cipher_Type_To_Str(uint8_t CipherType);
|
||||
uint16_t CRC15BitNXDN(uint8_t * BufferIn, uint32_t BitLength);
|
||||
uint16_t CRC12BitNXDN(uint8_t * BufferIn, uint32_t BitLength);
|
||||
uint8_t CRC6BitNXDN(uint8_t * BufferIn, uint32_t BitLength);
|
||||
void ScrambledNXDNVoiceBit(int * LfsrValue, char * BufferIn, char * BufferOut, int NbOfBitToScramble);
|
||||
|
||||
|
||||
void dPMRVoiceFrameProcess(dsd_opts * opts, dsd_state * state);
|
||||
void printdPMRAmbeVoiceSample(dsd_opts * opts, dsd_state * state);
|
||||
void printdPMRRawVoiceFrame (dsd_opts * opts, dsd_state * state);
|
||||
|
||||
//dPMR functions
|
||||
void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferOut, uint32_t NbOfBitToScramble);
|
||||
void DeInterleave6x12DPmrBit(uint8_t * BufferIn, uint8_t * BufferOut);
|
||||
@@ -825,11 +837,11 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_
|
||||
void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessMBCData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessMBChData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessWTFData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessReservedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessUnifiedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
|
||||
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
||||
int LFSR(dsd_state * state);
|
||||
int LFSRP(dsd_state * state);
|
||||
|
||||
void Hamming_7_4_init();
|
||||
void Hamming_7_4_encode(unsigned char *origBits, unsigned char *encodedBits);
|
||||
@@ -876,7 +888,7 @@ extern "C" {
|
||||
#endif
|
||||
void open_rtlsdr_stream(dsd_opts *opts);
|
||||
void cleanup_rtlsdr_stream();
|
||||
void get_rtlsdr_sample(int16_t *sample);
|
||||
void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state);
|
||||
void rtlsdr_sighandler();
|
||||
|
||||
//TRELLIS
|
||||
@@ -890,8 +902,6 @@ void CDMRTrellisPointsToDibits(const unsigned char* points, signed char* dibits)
|
||||
void CDMRTrellisBitsToTribits(const unsigned char* payload, unsigned char* tribits);
|
||||
bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@ extern const int DSDNXDN_UDCH_m_PunctureList[58];
|
||||
*/
|
||||
const char nxdnpr[145] = { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1 };
|
||||
//const unsigned char nxdnpr2[384] =
|
||||
const unsigned char nxdnpr2[182] = //is this a problem, should it be 384/2 for dibits?
|
||||
const unsigned char nxdnpr2[182] = //generated from default in manual with the x^9+x^4+1 poly?
|
||||
{
|
||||
0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0,
|
||||
|
||||
145
src/dmr_bs.c
145
src/dmr_bs.c
@@ -10,13 +10,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
char ambe_fr[4][24] = {0};
|
||||
char ambe_fr2[4][24] = {0};
|
||||
char ambe_fr3[4][24] = {0};
|
||||
char t_ambe_fr[4][24] = {9};
|
||||
char t_ambe_fr2[4][24] = {9};
|
||||
char t_ambe_fr3[4][24] = {9};
|
||||
|
||||
const int *w, *x, *y, *z;
|
||||
char sync[25] = {0};
|
||||
char syncdata[48] = {0};
|
||||
char cachdata[13] = {0};
|
||||
//char cachdata[13] = {0};
|
||||
int mutecurrentslot;
|
||||
int msMode;
|
||||
char cc[4];
|
||||
@@ -29,6 +27,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
unsigned short int vc1;
|
||||
unsigned short int vc2;
|
||||
|
||||
//cach fec
|
||||
char cachdata[25] = {0}; //increased from 24 to 25 to see if this fixes ubuntu 32 bug
|
||||
int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23};
|
||||
|
||||
|
||||
//add time to mirror printFrameSync
|
||||
time_t now;
|
||||
char * getTime(void) //get pretty hh:mm:ss timestamp
|
||||
@@ -67,17 +70,34 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
for(i = 0; i < 12; i++)
|
||||
{
|
||||
dibit = getDibit(opts, state);
|
||||
cachdata[i] = dibit;
|
||||
state->dmr_stereo_payload[i] = dibit;
|
||||
//fprintf (stderr, "D%X ", dibit);
|
||||
//fprintf (stderr, "P%X ", state->dmr_stereo_payload[i]);
|
||||
if(i == 2)
|
||||
{
|
||||
state->currentslot = (1 & (dibit >> 1));
|
||||
internalslot = (1 & (dibit >> 1));
|
||||
}
|
||||
|
||||
cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
||||
cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
||||
}
|
||||
|
||||
cachdata[25] = 0; //setting to see if this fixes ubuntu 32 bit bug
|
||||
|
||||
//decode and correct cach and compare
|
||||
int cach_okay = 69;
|
||||
if ( Hamming_7_4_decode (cachdata) ) //see if we need to de-interleave this...probably do.
|
||||
{
|
||||
cach_okay = 1;
|
||||
}
|
||||
if (cach_okay == 1)
|
||||
{
|
||||
//fprintf (stderr, "CACH Okay ");
|
||||
}
|
||||
if (cach_okay != 1)
|
||||
{
|
||||
//fprintf (stderr, "CACH FEC Error %d", cach_okay);
|
||||
}
|
||||
|
||||
state->currentslot = cachdata[1];
|
||||
internalslot = cachdata[1];
|
||||
|
||||
//this cach fec seems to work quite well, really helps on shaky signals
|
||||
|
||||
//Setup for first AMBE Frame
|
||||
//Interleave Schedule
|
||||
w = rW;
|
||||
@@ -140,19 +160,24 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//short int l = 0; //do I still use this?
|
||||
// signaling data or sync
|
||||
long long int late_entry_pi[24] = {0};
|
||||
short int m = 0;
|
||||
for(i = 0; i < 24; i++)
|
||||
{
|
||||
dibit = getDibit(opts, state);
|
||||
|
||||
state->dmr_stereo_payload[i+66] = dibit;
|
||||
syncdata[(2*i)] = (1 & (dibit >> 1)); // bit 1
|
||||
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
||||
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
||||
sync[i] = (dibit | 1) + 48;
|
||||
|
||||
if (i < 4 || i > 19) //
|
||||
if (i < 4 || i > 19)
|
||||
{
|
||||
EmbeddedSignalling[2*i] = (1 & (dibit >> 1)); // bit 1
|
||||
EmbeddedSignalling[2*i+1] = (1 & dibit); // bit 0
|
||||
// fprintf(stderr, "\n EMB = ");
|
||||
EmbeddedSignalling[(2*i)] = (1 & (dibit >> 1)); // bit 1
|
||||
//fprintf (stderr, "%02b", dibit);
|
||||
EmbeddedSignalling[(2*i)+1] = (1 & dibit); // bit 0
|
||||
|
||||
}
|
||||
|
||||
//Used for ProcessVoiceBurstSync
|
||||
@@ -168,6 +193,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1
|
||||
state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2+1] = (1 & dibit); // bit 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sync[24] = 0;
|
||||
@@ -194,9 +220,20 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
state->LCSS = (unsigned int)((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
|
||||
state->LCSS_ok = EmbeddedSignallingOk;
|
||||
|
||||
}
|
||||
else skipcount++;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
//fprintf (stderr, " %b", EmbeddedSignalling[i]);
|
||||
}
|
||||
|
||||
}
|
||||
//else skipcount++;
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
//fprintf (stderr, " %b", EmbeddedSignalling[i]);
|
||||
}
|
||||
}
|
||||
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
|
||||
for(i = 0; i < 18; i++)
|
||||
{
|
||||
@@ -248,15 +285,27 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
if (internalslot == 0)
|
||||
{
|
||||
vc1 = 1;
|
||||
state->dropL = 256;
|
||||
}
|
||||
if (internalslot == 1)
|
||||
{
|
||||
vc2 = 1;
|
||||
state->dropR = 256;
|
||||
}
|
||||
}
|
||||
|
||||
// if( strcmp (sync, DMR_DIRECT_MODE_TS1_DATA_SYNC) == 0)
|
||||
// {
|
||||
// fprintf (stderr,"%s ", getTime());
|
||||
// fprintf (stderr, " Sync: DMR TDMA Direct Mode TS 1 \n");
|
||||
// goto SKIP;
|
||||
// }
|
||||
//
|
||||
// if( strcmp (sync, DMR_DIRECT_MODE_TS2_DATA_SYNC) == 0)
|
||||
// {
|
||||
// fprintf (stderr,"%s ", getTime());
|
||||
// fprintf (stderr, " Sync: DMR TDMA Direct Mode TS 2 \n");
|
||||
// goto SKIP;
|
||||
// }
|
||||
|
||||
//check for sync pattern here after collected the rest of the payload, decide what to do with it
|
||||
if ( strcmp (sync, DMR_BS_DATA_SYNC) == 0 )
|
||||
{
|
||||
@@ -273,7 +322,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
else fprintf (stderr,"Sync: -DMR ");
|
||||
//constantly reset the vc counter to 1 each data frame in anticipation of new voice frame
|
||||
vc1 = 1;
|
||||
//state->dropL = 256;
|
||||
|
||||
}
|
||||
if (internalslot == 1)
|
||||
{
|
||||
@@ -287,7 +336,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
else fprintf (stderr,"Sync: -DMR ");
|
||||
//constantly reset the vc counter to 1 each data frame in anticipation of new voice frame
|
||||
vc2 = 1;
|
||||
//state->dropR = 256;
|
||||
|
||||
}
|
||||
processDMRdata (opts, state);
|
||||
skipcount++; //after 2 data frames, drop back to getFrameSync and process subsequent data with processDMRdata
|
||||
@@ -304,6 +353,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
//only play voice on no data sync
|
||||
if (strcmp (sync, DMR_BS_DATA_SYNC) != 0)
|
||||
{
|
||||
|
||||
if (EmbeddedSignallingOk == 0)
|
||||
{
|
||||
//goto END;
|
||||
@@ -314,7 +364,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
if (internalslot == 0)
|
||||
{
|
||||
state->dmrburstL = 16; //use 16 for Voice?
|
||||
//fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->dmr_color_code, vc1);
|
||||
|
||||
if (opts->inverted_dmr == 0)
|
||||
{
|
||||
fprintf (stderr,"Sync: +DMR [SLOT1] slot2 | | DMRSTEREO | VC%d ",vc1);
|
||||
@@ -324,11 +374,6 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//the condition below should be swapped to vc6 and not on vc1, placement after processMbeFrame
|
||||
if (vc1 == 1 && state->payload_algid != 0 && opts->payload == 1)
|
||||
{
|
||||
//LFSR(state); //placement here causes issues when second slot becomes active as well
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
else
|
||||
@@ -340,11 +385,6 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//the condition below should be swapped to vc6 and not on vc1, placement after processMbeFrame
|
||||
if (vc1 == 1 && state->payload_algid != 0 && opts->payload == 1)
|
||||
{
|
||||
//LFSR(state); //placement here causes issues when second slot becomes active as well
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
@@ -361,11 +401,6 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//the condition below should be swapped to vc6 and not on vc1, placement after processMbeFrame
|
||||
if (vc2 == 1 && state->payload_algidR != 0 && opts->payload == 1)
|
||||
{
|
||||
//LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
else
|
||||
@@ -377,11 +412,6 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//the condition below should be swapped to vc6 and not on vc1, placement after processMbeFrame
|
||||
if (vc2 == 1 && state->payload_algidR != 0 && opts->payload == 1)
|
||||
{
|
||||
//LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
@@ -403,29 +433,31 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||
|
||||
//We only want to run LFSR after processing VC6 frames and before rolling
|
||||
//back to VC1, otherwise we will incur an unwanted LFSR if voice becomes active
|
||||
//in both slots while in this loop
|
||||
if (internalslot == 0 && vc1 == 6)
|
||||
{
|
||||
state->dropL = 256;
|
||||
if (state->payload_algid != 0 ) //&& opts->payload == 1
|
||||
|
||||
if (state->payload_algid >= 0x21)
|
||||
{
|
||||
LFSR(state);
|
||||
//running this as state->payload_mi > 0 apparently causes some problem, don't know why
|
||||
if (state->payload_mi != 0 && state->payload_algid >= 0x21)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (internalslot == 1 && vc2 == 6)
|
||||
{
|
||||
state->dropR = 256;
|
||||
if (state->payload_algidR != 0 ) //&& opts->payload == 1
|
||||
|
||||
if (state->payload_algidR >= 0x21)
|
||||
{
|
||||
LFSR(state);
|
||||
if (state->payload_miR != 0 && state->payload_algidR == 0x21)
|
||||
{
|
||||
LFSR(state); //re-enable this one after testing Late Entry MI
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (internalslot == 0)
|
||||
@@ -436,6 +468,7 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
vc2++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// recalibrate center/umid/lmid, not sure this helps or does anything particularly in this case
|
||||
@@ -677,10 +710,6 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
//these ambe_fr values are set correctly now!
|
||||
//reset drop values since we don't know which slot (because I'm too lazy to write that part)
|
||||
state->dropL = 256;
|
||||
state->dropR = 256;
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||
|
||||
124
src/dmr_data.c
124
src/dmr_data.c
@@ -25,14 +25,17 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
int *dibit_p;
|
||||
char sync[25];
|
||||
char syncdata[48];
|
||||
char cachdata[13] = {0};
|
||||
char cachdata[25] = {0}; //increased from 24 to 25 to see if this fixes ubuntu 32 bug
|
||||
char cc[5] = {0};
|
||||
char ccAscii[5] = {0};
|
||||
char bursttype[5];
|
||||
unsigned int burst;
|
||||
char info[196];
|
||||
char SlotType[20];
|
||||
// char SlotType[20]; //was char, but I don't think FEC brings back good values when usign that
|
||||
unsigned char SlotType[20]; //was char, but I don't think FEC brings back good values when usign that
|
||||
unsigned int SlotTypeOk;
|
||||
int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23};
|
||||
|
||||
|
||||
/* Remove warning compiler */
|
||||
//UNUSED_VARIABLE(cachdata[0]);
|
||||
@@ -57,7 +60,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
dibit_p = state->dmr_payload_p - 90;
|
||||
}
|
||||
|
||||
// CACH
|
||||
// CACH, why aren't we running any FEC on this?
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
dibit = *dibit_p;
|
||||
@@ -71,31 +74,72 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
dibit = (int)state->dmr_stereo_payload[i];
|
||||
}
|
||||
//fprintf(stderr, "%X", dibit);
|
||||
cachdata[i] = dibit;
|
||||
//cachdata[i] = dibit;
|
||||
|
||||
cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
||||
cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
||||
// cachdata[(i*2)] = (1 & (dibit >> 1)); // bit 1
|
||||
// cachdata[(i*2)+1] = (1 & dibit); // bit 0
|
||||
|
||||
if (i == 2)
|
||||
{
|
||||
/* Change the current slot only if we are in relayed mode (not in direct mode) */
|
||||
if(state->directmode == 0) state->currentslot = (1 & (dibit >> 1)); // bit 1
|
||||
|
||||
if (state->currentslot == 0 && state->dmr_ms_mode == 0)
|
||||
{
|
||||
state->slot1light[0] = '[';
|
||||
state->slot1light[6] = ']';
|
||||
state->slot2light[0] = ' ';
|
||||
state->slot2light[6] = ' ';
|
||||
}
|
||||
//else
|
||||
if (state->currentslot == 1 && state->dmr_ms_mode == 0)
|
||||
{
|
||||
state->slot2light[0] = '[';
|
||||
state->slot2light[6] = ']';
|
||||
state->slot1light[0] = ' ';
|
||||
state->slot1light[6] = ' ';
|
||||
}
|
||||
// if(state->directmode == 0) state->currentslot = (1 & (dibit >> 1)); //move this until after cach fec performed
|
||||
//
|
||||
// if (state->currentslot == 0 && state->dmr_ms_mode == 0)
|
||||
// {
|
||||
// state->slot1light[0] = '[';
|
||||
// state->slot1light[6] = ']';
|
||||
// state->slot2light[0] = ' ';
|
||||
// state->slot2light[6] = ' ';
|
||||
// }
|
||||
// //else
|
||||
// if (state->currentslot == 1 && state->dmr_ms_mode == 0)
|
||||
// {
|
||||
// state->slot2light[0] = '[';
|
||||
// state->slot2light[6] = ']';
|
||||
// state->slot1light[0] = ' ';
|
||||
// state->slot1light[6] = ' ';
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
cachdata[12] = 0;
|
||||
//cachdata[12] = 0;
|
||||
cachdata[25] = 0; //setting to see if this fixes ubuntu 32 bit bug
|
||||
//decode and correct cach and compare
|
||||
int cach_okay = 69;
|
||||
if ( Hamming_7_4_decode (cachdata) ) //is now de-interleaved appropriately
|
||||
{
|
||||
cach_okay = 1;
|
||||
}
|
||||
if (cach_okay == 1)
|
||||
{
|
||||
//fprintf (stderr, "CACH Okay ");
|
||||
}
|
||||
if (cach_okay != 1)
|
||||
{
|
||||
//fprintf (stderr, "CACH FEC Error %d", cach_okay);
|
||||
goto END;
|
||||
}
|
||||
|
||||
state->currentslot = cachdata[1]; //still bit 2, or somewhere else? is it 8? 1? TC?
|
||||
|
||||
if (state->currentslot == 0 && state->dmr_ms_mode == 0)
|
||||
{
|
||||
state->slot1light[0] = '[';
|
||||
state->slot1light[6] = ']';
|
||||
state->slot2light[0] = ' ';
|
||||
state->slot2light[6] = ' ';
|
||||
}
|
||||
//else
|
||||
if (state->currentslot == 1 && state->dmr_ms_mode == 0)
|
||||
{
|
||||
state->slot2light[0] = '[';
|
||||
state->slot2light[6] = ']';
|
||||
state->slot1light[0] = ' ';
|
||||
state->slot1light[6] = ' ';
|
||||
}
|
||||
//end correct cach and set slot
|
||||
|
||||
#ifdef DMR_DUMP
|
||||
k = 0;
|
||||
@@ -232,7 +276,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
||||
sync[i] = (dibit | 1) + 48;
|
||||
}
|
||||
sync[24] = 0;
|
||||
sync[24] = 0; //why?
|
||||
|
||||
#ifdef DMR_DUMP
|
||||
k = 0;
|
||||
@@ -296,8 +340,18 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
|
||||
/* Check and correct the SlotType (apply Golay(20,8) FEC check) */
|
||||
if(Golay_20_8_decode((unsigned char *)SlotType)) SlotTypeOk = 1;
|
||||
else SlotTypeOk = 0;
|
||||
//pretty sure this isn't working correcty, does not apply corrected bits, due to cast type mismatching
|
||||
// if(Golay_20_8_decode((unsigned char *)SlotType)) SlotTypeOk = 1;
|
||||
if( Golay_20_8_decode(SlotType) )
|
||||
{
|
||||
SlotTypeOk = 1;
|
||||
//fprintf (stderr, "Slot Okay ");
|
||||
}
|
||||
else
|
||||
{
|
||||
SlotTypeOk = 0;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Slot Type parity checked => Fill the color code */
|
||||
//state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]);
|
||||
@@ -469,14 +523,14 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
/* Burst = MBC Header */
|
||||
case 0b0100:
|
||||
{
|
||||
//ProcessMBChData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
ProcessMBChData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = MBC Continuation*/
|
||||
case 0b0101:
|
||||
{
|
||||
//ProcessMBCData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
ProcessMBCData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -512,14 +566,14 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
/* Burst = Rate 1 DATA */
|
||||
case 0b1010:
|
||||
{
|
||||
//Process1Data(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
Process1Data(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = Unified Single Block DATA */
|
||||
case 0b1101:
|
||||
{
|
||||
//ProcessUnifiedData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
ProcessUnifiedData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -527,7 +581,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
default:
|
||||
{
|
||||
/* Nothing to do */
|
||||
//ProcessWTFData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
ProcessReservedData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
} /* End switch(burst) */
|
||||
@@ -536,5 +590,13 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
//JUMP:
|
||||
END:
|
||||
if (SlotTypeOk == 0 || cach_okay == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, " **CACH or Burst Type FEC ERR - SKIPPING** ");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
} /* End processDMRdata() */
|
||||
|
||||
143
src/dmr_ms.c
143
src/dmr_ms.c
@@ -33,6 +33,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
char redundancyB[36];
|
||||
unsigned short int vc1;
|
||||
unsigned short int vc2;
|
||||
|
||||
//add time to mirror printFrameSync
|
||||
time_t now;
|
||||
char * getTime(void) //get pretty hh:mm:ss timestamp
|
||||
@@ -60,12 +61,15 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
short int skipcount = 0;
|
||||
|
||||
//Hardset variables for MS
|
||||
state->currentslot = 0;
|
||||
state->currentslot = 0; //0
|
||||
internalslot = 0;
|
||||
activeslot = 0;
|
||||
|
||||
//Run Loop while the getting is good
|
||||
while (loop == 1) {
|
||||
|
||||
short int m = 0;
|
||||
|
||||
state->dmrburstL = 16; //Use 16 for Voice?
|
||||
// No CACH in MS Mode?
|
||||
for(i = 0; i < 12; i++)
|
||||
@@ -258,17 +262,9 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
y++;
|
||||
z++;
|
||||
|
||||
//end early to allow next sync without skipping a voice superframe
|
||||
//only use if only doing 6 VC and nothing else, otherwise, will lose sync
|
||||
if (vc1 == 6 && i == 30)
|
||||
{
|
||||
//i = 36;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if ( (strcmp (sync, DMR_MS_VOICE_SYNC) == 0) )
|
||||
//fixed to compensate for inverted signal
|
||||
if ( ((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) && opts->inverted_dmr == 0) ||
|
||||
((strcmp (sync, DMR_MS_DATA_SYNC) == 0) && opts->inverted_dmr == 1) )
|
||||
|
||||
@@ -276,29 +272,18 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
if (internalslot == 0)
|
||||
{
|
||||
vc1 = 1;
|
||||
state->dropL = 256;
|
||||
fprintf (stderr, "MS Slot 1 Voice Sync \n");
|
||||
//activeslot = 0;
|
||||
|
||||
}
|
||||
|
||||
if (internalslot == 1)
|
||||
{
|
||||
vc2 = 1;
|
||||
state->dropR = 256;
|
||||
//fprintf (stderr, "MS Slot 2 Voice Sync \n");
|
||||
//activeslot = 1;
|
||||
}
|
||||
|
||||
state->dmr_ms_mode = 1; //set to 1 here??
|
||||
}
|
||||
|
||||
state->dmr_ms_mode = 1; //set to 1 here?
|
||||
//testing to see if we need to do something to get MS mode working properly,
|
||||
//get proper sync, skip frames, etc.
|
||||
if (state->dmr_ms_mode == 1 ) //&& vc1 < 7
|
||||
{
|
||||
//do something
|
||||
//fprintf (stderr, "MS MODE ");
|
||||
}
|
||||
|
||||
//don't know if we will catch an RC sync in here or not, should be on VC6 if it occurs
|
||||
if ( (strcmp (rcsync, DMR_RC_DATA_SYNC) == 0) || (strcmp (sync, DMR_RC_DATA_SYNC) == 0) ) //should be in same position as sync
|
||||
@@ -370,9 +355,6 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
goto END;
|
||||
}
|
||||
|
||||
//if( (strcmp (sync, DMR_MS_DATA_SYNC) != 0) && internalslot == activeslot && vc1 < 7)
|
||||
//only play voice no MS Data Sync and vc1 below 6 (no voice resync)
|
||||
//fixed to compensate for inverted signal
|
||||
if( ( ( ((strcmp (sync, DMR_MS_DATA_SYNC) != 0) && opts->inverted_dmr == 0) ||
|
||||
((strcmp (sync, DMR_MS_VOICE_SYNC) != 0) && opts->inverted_dmr == 1) ) )
|
||||
&& internalslot == activeslot && vc1 < 7)
|
||||
@@ -390,10 +372,6 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
if (vc1 == 6 && state->payload_algid != 0 && opts->payload == 1)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
@@ -406,67 +384,32 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
if (vc1 == 6 && state->payload_algid != 0 && opts->payload == 1)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
if (internalslot == 1 && opts->inverted_dmr == 0)
|
||||
{
|
||||
fprintf (stderr,"Sync: +DMR MS MODE | Color Code=%02d | DMRSTEREO | VC%d ", state->color_code, vc2);
|
||||
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
if (vc2 == 6 && state->payload_algidR != 0 && opts->payload == 1)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
if (internalslot == 1 && opts->inverted_dmr == 1)
|
||||
{
|
||||
fprintf (stderr,"Sync: -DMR MS MODE | Color Code=%02d | DMRSTEREO | VC%d ", state->color_code, vc2);
|
||||
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf(stderr, " BPK %lld", state->K);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
if (vc2 == 6 && state->payload_algidR != 0 && opts->payload == 1)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
if (internalslot == 0 && vc1 == 6) //presumably when full (and no sync issues)
|
||||
{
|
||||
//process voice burst
|
||||
ProcessVoiceBurstSync(opts, state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
if (internalslot == 1 && vc2 == 6) //presumably when full (and no sync issues)
|
||||
{
|
||||
//process voice burst
|
||||
//ProcessVoiceBurstSync(opts, state);
|
||||
//fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
state->dmr_ms_mode == 1;
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||
if (internalslot == 0)
|
||||
|
||||
//need to seperate the algs here so we don't run LFSR on 22 and so on
|
||||
if (vc1 == 6 && state->payload_algid >= 21)
|
||||
{
|
||||
//vc1++;
|
||||
}
|
||||
if (internalslot == 1)
|
||||
{
|
||||
vc2++;
|
||||
}
|
||||
//state->currentslot = 0;
|
||||
if (state->payload_mi != 0 && state->payload_algid >= 0x21)
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
vc1++;
|
||||
//6 seems optimal for MS, allows to quickly exit and resync if wonky or something
|
||||
@@ -692,13 +635,13 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
//reset drop values since we don't know which slot (because I'm too lazy to write that part)
|
||||
state->dropL = 256;
|
||||
state->dropR = 256;
|
||||
|
||||
state->dmr_ms_mode = 1;
|
||||
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||
|
||||
skipDibit (opts, state, 144); //skip to next TDMA slot
|
||||
dmrMS (opts, state); //bootstrap into full TDMA frame
|
||||
|
||||
@@ -706,11 +649,17 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
void dmrMSData (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int i;
|
||||
int i, b, c;
|
||||
int dibit;
|
||||
int *dibit_p;
|
||||
unsigned int burst;
|
||||
|
||||
unsigned char MSCach[24] = {0}; //12 dibits = 24 bits
|
||||
unsigned char MSSync[48] = {0}; //24 dibits = 48 bits
|
||||
unsigned char MSSlot[20] = {0}; //10 dibits = 20 bits
|
||||
unsigned char MSBurst[5] = {0};
|
||||
int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23};
|
||||
//int cachInterleave[24] = {0,}
|
||||
//add time to mirror sync
|
||||
time_t now;
|
||||
char * getTime(void) //get pretty hh:mm:ss timestamp
|
||||
@@ -727,7 +676,8 @@ void dmrMSData (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
b = 0;
|
||||
c = 0;
|
||||
//CACH + First Half Payload + Sync = 12 + 54 + 24
|
||||
//dibit_p = state->dibit_buf_p - 90;
|
||||
dibit_p = state->dmr_payload_p - 90;
|
||||
@@ -740,14 +690,42 @@ void dmrMSData (dsd_opts * opts, dsd_state * state)
|
||||
dibit = (dibit ^ 2);
|
||||
}
|
||||
state->dmr_stereo_payload[i] = dibit;
|
||||
//load cach
|
||||
if (i < 12)
|
||||
{
|
||||
MSCach[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
||||
MSCach[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
||||
}
|
||||
//load slot, first half
|
||||
if (i > 60 && i < 66)
|
||||
{
|
||||
MSSlot[(b*2)] = (1 & (dibit >> 1)); // bit 1
|
||||
MSSlot[(b*2)+1] = (1 & dibit); // bit
|
||||
b++;
|
||||
}
|
||||
//load sync
|
||||
if (i > 66)
|
||||
{
|
||||
MSSync[(c*2)] = (1 & (dibit >> 1)); // bit 1
|
||||
MSSync[(c*2)+1] = (1 & dibit); // bit 0
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 54; i++)
|
||||
{
|
||||
dibit = getDibit(opts, state);
|
||||
state->dmr_stereo_payload[i+90] = dibit;
|
||||
//load slot, second half
|
||||
if (i < 6)
|
||||
{
|
||||
MSSlot[(b*2)] = (1 & (dibit >> 1)); // bit 1
|
||||
MSSlot[(b*2)+1] = (1 & dibit); // bit
|
||||
b++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//hide behind payload due to errs in data in MS mode
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
@@ -775,9 +753,6 @@ void dmrMSData (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
state->dmr_stereo = 0;
|
||||
state->dmr_ms_mode = 0;
|
||||
//reset drop values since we don't know which slot (because I'm too lazy to write that part)
|
||||
state->dropL = 256;
|
||||
state->dropR = 256;
|
||||
|
||||
//get potential first half payload dibits and store them in the payload for the next repitition, MS voice or data.
|
||||
skipDibit (opts, state, 144);
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
#include "dmr_const.h"
|
||||
#include "p25p1_check_hdu.h"
|
||||
|
||||
//
|
||||
//A
|
||||
//
|
||||
|
||||
void ProcessDMR (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
uint32_t i, j;
|
||||
@@ -40,7 +36,6 @@ void ProcessDMR (dsd_opts * opts, dsd_state * state)
|
||||
TSVoiceSupFrameL = &state->TS1SuperFrame;
|
||||
TSVoiceSupFrameR = &state->TS2SuperFrame;
|
||||
|
||||
//
|
||||
int BP[256] = {
|
||||
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
|
||||
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
|
||||
@@ -75,9 +70,8 @@ int BP[256] = {
|
||||
0x0BF0, 0x14F0, 0xE8F0, 0xF7F0, 0x2EF3, 0x31F3, 0xCDF3, 0xD2F3,
|
||||
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255
|
||||
};
|
||||
//
|
||||
//H
|
||||
//
|
||||
|
||||
|
||||
if (state->currentslot == 0 && state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
@@ -85,12 +79,12 @@ if (state->currentslot == 0 && state->K > 0 && state->dmr_so & 0x40 && state->pa
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
k = BP[state->K];
|
||||
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
||||
|
||||
|
||||
for(Frame = 0; Frame < 6; Frame++)
|
||||
{
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
for(j = 0; j < 49; j++)
|
||||
for(j = 0; j < 48; j++)
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x;
|
||||
@@ -111,7 +105,7 @@ if (state->currentslot == 1 && state->K > 0 && state->dmr_soR & 0x40 && state->p
|
||||
{
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
for(j = 0; j < 49; j++)
|
||||
for(j = 0; j < 48; j++)
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x;
|
||||
@@ -119,15 +113,10 @@ if (state->currentslot == 1 && state->K > 0 && state->dmr_soR & 0x40 && state->p
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//B
|
||||
//
|
||||
|
||||
if (state->currentslot == 0)
|
||||
{
|
||||
if (opts->payload == 1 && state->R == 0)
|
||||
{
|
||||
fprintf(stderr, "\n"); //line break for AMBE printer
|
||||
}
|
||||
|
||||
for(Frame = 0; Frame < 6; Frame++) //6
|
||||
{
|
||||
/* 1 DMR frame contains 3 AMBE voice samples */
|
||||
@@ -147,35 +136,43 @@ if (state->currentslot == 0)
|
||||
PrintAMBEData(opts, state, TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
}
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
//quick enc toggle to determine whether or not to play enc traffic
|
||||
int enc_bit = 0;
|
||||
enc_bit = (state->dmr_so >> 6) & 0x1;
|
||||
if (enc_bit == 1)
|
||||
{
|
||||
saveAmbe2450Data (opts, state, TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
state->dmr_encL = 1;
|
||||
}
|
||||
|
||||
state->debug_audio_errors += *errs2;
|
||||
|
||||
processAudio(opts, state);
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
else state->dmr_encL = 0;
|
||||
//quick test to determine whether or not to run the next few steps below
|
||||
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
||||
{
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveAmbe2450Data (opts, state, TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
}
|
||||
|
||||
//play only if not equal to enc value, going to set p25enc to 1 if enc detected??
|
||||
if (opts->audio_out == 1 && opts->p25enc != 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
}
|
||||
state->debug_audio_errors += *errs2;
|
||||
|
||||
processAudio(opts, state);
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
|
||||
if (opts->audio_out == 1) //opts->audio_out == 1
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
}
|
||||
} //second bracket for the test enc condition
|
||||
} /* End for(i = 0; i < 3; i++) */
|
||||
} /* End for(Frame = 0; Frame < 6; Frame++) */
|
||||
} //End if Current Slot == 0
|
||||
|
||||
if (state->currentslot == 1)
|
||||
{
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
fprintf(stderr, "\n"); //line break for AMBE printer
|
||||
}
|
||||
|
||||
for(Frame = 0; Frame < 6; Frame++)
|
||||
{
|
||||
/* 1 DMR frame contains 3 AMBE voice samples */
|
||||
@@ -196,24 +193,36 @@ if (state->currentslot == 0)
|
||||
PrintAMBEData(opts, state, TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
}
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
//quick enc toggle to determine whether or not to play enc traffic
|
||||
int enc_bit = 0;
|
||||
enc_bit = (state->dmr_soR >> 6) & 0x1;
|
||||
if (enc_bit == 1)
|
||||
{
|
||||
saveAmbe2450Data (opts, state, TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
state->dmr_encR = 1;
|
||||
}
|
||||
else state->dmr_encR = 0;
|
||||
|
||||
state->debug_audio_errors += *errs2;
|
||||
|
||||
processAudio(opts, state);
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
//quick test to determine whether or not to run the next few steps below
|
||||
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
||||
{
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveAmbe2450Data (opts, state, TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
|
||||
}
|
||||
|
||||
//play only if not equal to enc value, going to set p25enc to 1 if enc detected??
|
||||
if (opts->audio_out == 1 && opts->p25enc != 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
state->debug_audio_errors += *errs2;
|
||||
|
||||
processAudio(opts, state);
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
}
|
||||
}
|
||||
} /* End for(i = 0; i < 3; i++) */
|
||||
} /* End for(Frame = 0; Frame < 6; Frame++) */
|
||||
|
||||
1457
src/dmr_sync.c
1457
src/dmr_sync.c
File diff suppressed because it is too large
Load Diff
@@ -646,8 +646,8 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
|
||||
ProcessDMR(opts, state);
|
||||
|
||||
//LFSR if required, change condition?
|
||||
if ( (state->currentslot == 0 && state->payload_algid != 0 ) || //&& opts->payload == 1
|
||||
(state->currentslot == 1 && state->payload_algidR != 0 ) ) //&& opts->payload == 1
|
||||
if ( (state->currentslot == 0 && state->payload_algid == 0x21 ) || //&& opts->payload == 1
|
||||
(state->currentslot == 1 && state->payload_algidR == 0x21 ) ) //&& opts->payload == 1
|
||||
{
|
||||
LFSR(state);
|
||||
}
|
||||
|
||||
156
src/dsd_audio.c
156
src/dsd_audio.c
@@ -22,6 +22,20 @@ pa_sample_spec tt;
|
||||
pa_sample_spec zz;
|
||||
pa_sample_spec cc;
|
||||
|
||||
void closePulseOutput (dsd_opts * opts)
|
||||
{
|
||||
pa_simple_free (opts->pulse_digi_dev_out);
|
||||
if (opts->dmr_stereo == 1)
|
||||
{
|
||||
pa_simple_free (opts->pulse_digi_dev_outR);
|
||||
}
|
||||
}
|
||||
|
||||
void closePulseInput (dsd_opts * opts)
|
||||
{
|
||||
pa_simple_free (opts->pulse_digi_dev_in);
|
||||
}
|
||||
|
||||
void openPulseOutput(dsd_opts * opts)
|
||||
{
|
||||
|
||||
@@ -35,7 +49,7 @@ void openPulseOutput(dsd_opts * opts)
|
||||
|
||||
if (opts->monitor_input_audio == 1)
|
||||
{
|
||||
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Raw Audio Out", &ss, NULL, NULL, NULL);
|
||||
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME3", PA_STREAM_PLAYBACK, NULL, "Raw Audio Out", &ss, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
//tt
|
||||
@@ -47,10 +61,11 @@ void openPulseOutput(dsd_opts * opts)
|
||||
opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, opts->output_name, &tt, left, NULL, NULL);
|
||||
|
||||
}
|
||||
|
||||
if (opts->dmr_stereo == 1)
|
||||
{
|
||||
opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME1", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO SLOT 1", &tt, left, NULL, NULL);
|
||||
opts->pulse_digi_dev_outR = pa_simple_new(NULL, "DSD-FME2", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO SLOT 2", &tt, right, NULL, NULL);
|
||||
opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME1", PA_STREAM_PLAYBACK, NULL, "DMR SLOT 1", &tt, left, NULL, NULL);
|
||||
opts->pulse_digi_dev_outR = pa_simple_new(NULL, "DSD-FME2", PA_STREAM_PLAYBACK, NULL, "DMR SLOT 2", &tt, right, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -348,8 +363,7 @@ processAudioR (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
||||
void writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int n;
|
||||
short aout_buf[160];
|
||||
@@ -377,6 +391,50 @@ writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
}
|
||||
|
||||
void writeSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int n;
|
||||
short aout_buf[160];
|
||||
short *aout_buf_p;
|
||||
|
||||
aout_buf_p = aout_buf;
|
||||
state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
|
||||
|
||||
for (n = 0; n < 160; n++)
|
||||
{
|
||||
if (*state->audio_out_temp_buf_pR > (float) 32767)
|
||||
{
|
||||
*state->audio_out_temp_buf_pR = (float) 32767;
|
||||
}
|
||||
else if (*state->audio_out_temp_buf_pR < (float) -32768)
|
||||
{
|
||||
*state->audio_out_temp_buf_pR = (float) -32768;
|
||||
}
|
||||
*aout_buf_p = (short) *state->audio_out_temp_buf_pR;
|
||||
aout_buf_p++;
|
||||
state->audio_out_temp_buf_pR++;
|
||||
}
|
||||
|
||||
sf_write_short(opts->wav_out_fR, aout_buf, 160);
|
||||
|
||||
}
|
||||
|
||||
void writeRawSample (dsd_opts * opts, dsd_state * state, short sample)
|
||||
{
|
||||
int n;
|
||||
short aout_buf[160];
|
||||
short *aout_buf_p;
|
||||
|
||||
//sf_write_short(opts->wav_out_raw, aout_buf, 160);
|
||||
|
||||
//only write if actual audio, truncate silence
|
||||
if (sample != 0)
|
||||
{
|
||||
sf_write_short(opts->wav_out_raw, &sample, 2); //2 to match pulseaudio input sample read
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
@@ -396,22 +454,6 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
||||
state->audio_out_idx = 0;
|
||||
}
|
||||
|
||||
//most likely don't need this seperation anymore with L and R, just push it out without any condional checks
|
||||
/*
|
||||
if(state->currentslot == 0 && opts->audio_in_type != 3 && opts->dmr_stereo == 1)
|
||||
{
|
||||
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
|
||||
state->audio_out_idx = 0;
|
||||
}
|
||||
|
||||
//if input type is rtl dongle or no dmr stereo...do I need it this way still?
|
||||
if (opts->audio_in_type == 3 || opts->dmr_stereo == 0)
|
||||
{
|
||||
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
|
||||
state->audio_out_idx = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -443,14 +485,6 @@ playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
|
||||
pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works.
|
||||
state->audio_out_idxR = 0;
|
||||
}
|
||||
/*
|
||||
//most likely don't need this seperation anymore with L and R, just push it out without any condional checks
|
||||
if(opts->dmr_stereo == 1) //state->currentslot == 1 && opts->audio_in_type != 3 && opts->dmr_stereo == 1
|
||||
{
|
||||
pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works.
|
||||
state->audio_out_idxR = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -467,17 +501,13 @@ playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
|
||||
void
|
||||
openAudioOutDevice (dsd_opts * opts, int speed)
|
||||
{
|
||||
//converted to handle any calls to use portaudio
|
||||
if(strncmp(opts->audio_out_dev, "pa:", 3) == 0)
|
||||
{
|
||||
opts->audio_out_type = 2;
|
||||
#ifdef USE_PORTAUDIO
|
||||
int err = getPADevice(opts->audio_out_dev, 0, &opts->audio_out_pa_stream);
|
||||
if(err != 0)
|
||||
exit(err);
|
||||
#else
|
||||
fprintf (stderr,"Error, Portaudio support not compiled.\n");
|
||||
exit(1);
|
||||
#endif
|
||||
opts->audio_out_type = 0;
|
||||
fprintf (stderr,"Error, Port Audio is not supported by FME!\n");
|
||||
fprintf (stderr,"Using Pulse Audio Output Stream Instead! \n");
|
||||
sprintf (opts->audio_out_dev, "pulse");
|
||||
}
|
||||
if(strncmp(opts->audio_in_dev, "pulse", 5) == 0)
|
||||
{
|
||||
@@ -522,25 +552,13 @@ openAudioInDevice (dsd_opts * opts)
|
||||
exit(1); //had this one disabled, re-enabling it now
|
||||
}
|
||||
}
|
||||
//converted to handle any calls to use portaudio
|
||||
else if(strncmp(opts->audio_in_dev, "pa:", 2) == 0)
|
||||
{
|
||||
opts->audio_in_type = 2;
|
||||
#ifdef USE_PORTAUDIO
|
||||
int err = getPADevice(opts->audio_in_dev, 1, &opts->audio_in_pa_stream);
|
||||
if(err != 0)
|
||||
exit(err);
|
||||
|
||||
if (opts->split == 0)
|
||||
{
|
||||
int err = getPADevice(opts->audio_in_dev, 0, &opts->audio_out_pa_stream);
|
||||
if(err != 0)
|
||||
exit(err);
|
||||
}
|
||||
|
||||
#else
|
||||
fprintf (stderr,"Error, Portaudio support not compiled.\n");
|
||||
exit(1);
|
||||
#endif
|
||||
opts->audio_in_type = 0;
|
||||
fprintf (stderr,"Error, Port Audio is not supported by FME!\n");
|
||||
fprintf (stderr,"Using Pulse Audio Input Stream Instead! \n");
|
||||
sprintf (opts->audio_in_dev, "pulse");
|
||||
}
|
||||
else if(strncmp(opts->audio_in_dev, "rtl", 3) == 0)
|
||||
{
|
||||
@@ -550,28 +568,32 @@ openAudioInDevice (dsd_opts * opts)
|
||||
{
|
||||
opts->audio_in_type = 0;
|
||||
}
|
||||
//convert from opening wav files to OP25 symbol capture files since opening wav files is busted
|
||||
else
|
||||
{
|
||||
struct stat stat_buf;
|
||||
if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
||||
struct stat stat_buf;
|
||||
if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
||||
{
|
||||
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
|
||||
exit(1);
|
||||
}
|
||||
if (S_ISREG(stat_buf.st_mode))
|
||||
if (S_ISREG(stat_buf.st_mode))
|
||||
{
|
||||
// is this a regular file? then process with libsndfile.
|
||||
//opts->pulse_digi_rate_out = 8000; //this for wav files input?
|
||||
opts->audio_in_type = 1;
|
||||
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
|
||||
opts->audio_in_file_info->channels = 1;
|
||||
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
|
||||
// opts->audio_in_type = 1;
|
||||
// opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
|
||||
// opts->audio_in_file_info->channels = 1;
|
||||
// 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 file %s\n", opts->audio_in_dev);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
if(opts->audio_in_file == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error, couldn't open file %s\n", opts->audio_in_dev);
|
||||
exit(1);
|
||||
}
|
||||
opts->symbolfile = fopen(opts->audio_in_dev, "r");
|
||||
opts->audio_in_type = 4; //symbol capture bin files
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -376,6 +376,7 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
|
||||
*state->dmr_payload_p = dibit;
|
||||
state->dmr_payload_p++;
|
||||
//dmr buffer end
|
||||
|
||||
return dibit;
|
||||
}
|
||||
}
|
||||
@@ -386,6 +387,19 @@ get_dibit_and_analog_signal (dsd_opts* opts, dsd_state* state, int* out_analog_s
|
||||
int symbol;
|
||||
int dibit;
|
||||
|
||||
// if (opts->audio_in_type == 4 && opts->frame_provoice == 1) //
|
||||
// {
|
||||
// //skip processing symbol as dibit and use it as is
|
||||
// if (state->symbolc == 0)
|
||||
// {
|
||||
// symbol = 1;
|
||||
// }
|
||||
// if (state->symbolc == 1)
|
||||
// {
|
||||
// symbol = 3;
|
||||
// }
|
||||
// }
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
unsigned int l, r;
|
||||
#endif
|
||||
@@ -402,7 +416,7 @@ get_dibit_and_analog_signal (dsd_opts* opts, dsd_state* state, int* out_analog_s
|
||||
r = state->debug_sample_index;
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
state->sbuf[state->sidx] = symbol;
|
||||
|
||||
if (out_analog_signal != NULL)
|
||||
@@ -414,6 +428,21 @@ get_dibit_and_analog_signal (dsd_opts* opts, dsd_state* state, int* out_analog_s
|
||||
|
||||
dibit = digitize (opts, state, symbol);
|
||||
|
||||
//don't think this is quite right still, but should work, don't know why it doesn't
|
||||
if (opts->audio_in_type == 4 && opts->frame_provoice == 1) //
|
||||
{
|
||||
//skip processing symbol as dibit and use it as is
|
||||
dibit = state->symbolc;
|
||||
}
|
||||
|
||||
//symbol/dibit file capture/writing
|
||||
//need this bit here to capture dibits once sync starts
|
||||
if (opts->symbol_out == 1)
|
||||
{
|
||||
//fprintf (stderr, "%d", dibit);
|
||||
fputc (dibit, opts->symbol_out_f);
|
||||
}
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
{
|
||||
float left, right;
|
||||
|
||||
177
src/dsd_file.c
177
src/dsd_file.c
@@ -179,9 +179,9 @@ PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d) //For DMR Stere
|
||||
}
|
||||
else fprintf(stderr, " err = [%X] [%X] ", state->errsR, state->errs2R);
|
||||
b = ambe_d[48];
|
||||
if (opts->dmr_stereo == 1)
|
||||
if (opts->dmr_stereo == 1) //need to fix the printouts again
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -460,74 +460,113 @@ openWavOutFile (dsd_opts * opts, dsd_state * state)
|
||||
// state->wav_out_bytes = 0;
|
||||
|
||||
}
|
||||
void openWavOutFileL (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
void
|
||||
closeWavOutFile (dsd_opts * opts, dsd_state * state)
|
||||
SF_INFO info;
|
||||
info.samplerate = 8000; //8000
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
//opts->wav_out_f = sf_open (opts->wav_out_file, SFM_WRITE, &info);
|
||||
opts->wav_out_f = sf_open (opts->wav_out_file, SFM_RDWR, &info); //RDWR will append to file instead of overwrite file
|
||||
|
||||
if (opts->wav_out_f == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error - could not open wav output file %s\n", opts->wav_out_file);
|
||||
return;
|
||||
}
|
||||
|
||||
// state->wav_out_bytes = 0;
|
||||
|
||||
}
|
||||
|
||||
void openWavOutFileR (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
SF_INFO info;
|
||||
info.samplerate = 8000; //8000
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
//opts->wav_out_f = sf_open (opts->wav_out_file, SFM_WRITE, &info);
|
||||
opts->wav_out_fR = sf_open (opts->wav_out_fileR, SFM_RDWR, &info); //RDWR will append to file instead of overwrite file
|
||||
|
||||
if (opts->wav_out_f == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error - could not open wav output file %s\n", opts->wav_out_fileR);
|
||||
return;
|
||||
}
|
||||
|
||||
// state->wav_out_bytes = 0;
|
||||
|
||||
}
|
||||
|
||||
void openWavOutFileRaw (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
SF_INFO info;
|
||||
info.samplerate = 48000; //8000
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
//opts->wav_out_f = sf_open (opts->wav_out_file, SFM_WRITE, &info);
|
||||
//opts->wav_out_f = sf_open (opts->wav_out_file, SFM_RDWR, &info); //RDWR will append to file instead of overwrite file
|
||||
opts->wav_out_raw = sf_open (opts->wav_out_file_raw, SFM_RDWR, &info);
|
||||
if (opts->wav_out_raw == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error - could not open raw wav output file %s\n", opts->wav_out_file_raw);
|
||||
return;
|
||||
}
|
||||
|
||||
// state->wav_out_bytes = 0;
|
||||
|
||||
}
|
||||
|
||||
void closeWavOutFile (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
sf_close(opts->wav_out_f);
|
||||
|
||||
/*
|
||||
int length;
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
rewind (opts->wav_out_f);
|
||||
length = state->wav_out_bytes;
|
||||
|
||||
fprintf (stderr,opts->wav_out_f, "RIFF");
|
||||
// total length
|
||||
fputc (((36 + length) & 0xff), opts->≈≈);
|
||||
fputc ((((36 + length) >> 8) & 0xff), opts->wav_out_f);
|
||||
fputc ((((36 + length) >> 16) & 0xff), opts->wav_out_f);
|
||||
fputc ((((36 + length) >> 24) & 0xff), opts->wav_out_f);
|
||||
|
||||
fprintf (stderr,opts->wav_out_f, "WAVE");
|
||||
fprintf (stderr,opts->wav_out_f, "fmt ");
|
||||
|
||||
// length of format chunk
|
||||
fputc (16, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// always 0x1
|
||||
fputc (1, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// channels
|
||||
fputc (1, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// sample rate
|
||||
fputc (64, opts->wav_out_f);
|
||||
fputc (31, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// bytes per second
|
||||
fputc (128, opts->wav_out_f);
|
||||
fputc (62, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// block align
|
||||
fputc (2, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// bits/sample
|
||||
fputc (16, opts->wav_out_f);
|
||||
fputc (0, opts->wav_out_f);
|
||||
|
||||
// data chunk header
|
||||
fprintf (stderr,opts->wav_out_f, "data");
|
||||
|
||||
// length of data
|
||||
fputc ((length & 0xff), opts->wav_out_f);
|
||||
fputc (((length >> 8) & 0xff), opts->wav_out_f);
|
||||
fputc (((length >> 16) & 0xff), opts->wav_out_f);
|
||||
fputc (((length >> 24) & 0xff), opts->wav_out_f);
|
||||
|
||||
fflush (opts->wav_out_f);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void closeWavOutFileL (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
sf_close(opts->wav_out_f);
|
||||
}
|
||||
|
||||
void closeWavOutFileR (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
sf_close(opts->wav_out_fR);
|
||||
}
|
||||
|
||||
void closeWavOutFileRaw (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
sf_close(opts->wav_out_raw);
|
||||
}
|
||||
|
||||
void openSymbolOutFile (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
//Do something
|
||||
opts->symbol_out_f = fopen (opts->symbol_out_file, "w");
|
||||
}
|
||||
|
||||
void writeSymbolOutFile (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
//Do something
|
||||
|
||||
}
|
||||
|
||||
void closeSymbolOutFile (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
//Do something
|
||||
if (opts->symbol_out == 1)
|
||||
{
|
||||
if (opts->symbol_out_file != NULL) //check first, or issuing a second fclose will crash the SOFTWARE
|
||||
{
|
||||
fclose(opts->symbol_out_f); //free(): double free detected in tcache 2 (this is a new one) happens when closing more than once
|
||||
//noCarrier(opts, state); //free(): double free detected in tcache 2 (this is a new one)
|
||||
}
|
||||
|
||||
opts->symbol_out = 0; //set flag to 1
|
||||
//sprintf (opts->symbol_out_file, "fme-capture.bin"); //use fme for the symbol bin ext
|
||||
//openSymbolOutFile (opts, state);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
sprintf (state->fsubtype, " VOICE ");
|
||||
processNXDNVoice (opts, state);
|
||||
//ProcessNXDNFrame (opts, state, 0);
|
||||
return;
|
||||
}
|
||||
else if ((state->synctype == 16) || (state->synctype == 17)) //NXDN Data
|
||||
@@ -128,6 +129,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
sprintf (state->fsubtype, " DATA ");
|
||||
processNXDNData (opts, state);
|
||||
//ProcessNXDNFrame (opts, state, 0);
|
||||
return;
|
||||
}
|
||||
else if ((state->synctype == 6) || (state->synctype == 7))
|
||||
@@ -233,6 +235,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
if (opts->dmr_stereo == 1)
|
||||
{
|
||||
dmrMSData (opts, state);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -243,6 +246,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
state->err_str[0] = 0;
|
||||
sprintf (state->slot1light, " slot1 ");
|
||||
sprintf (state->slot2light, " slot2 ");
|
||||
state->payload_miP = 0; //zero out when switching back to data sync
|
||||
processDMRdata (opts, state);
|
||||
}
|
||||
//switch dmr_stereo to 0 when handling BS data frame syncs with processDMRdata
|
||||
@@ -251,6 +255,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
state->dmr_stereo = 0; //set the state to zero for handling pure data frames
|
||||
sprintf (state->slot1light, " slot1 ");
|
||||
sprintf (state->slot2light, " slot2 ");
|
||||
state->payload_miP = 0; //zero out when switching back to data sync
|
||||
processDMRdata (opts, state);
|
||||
}
|
||||
}
|
||||
@@ -314,6 +319,19 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
processYSF(opts, state);
|
||||
return;
|
||||
}
|
||||
//P25 P2
|
||||
else if ((state->synctype == 35) || (state->synctype == 36))
|
||||
{
|
||||
//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 ");
|
||||
processP2(opts, state);
|
||||
return;
|
||||
}
|
||||
//dPMR
|
||||
else if ((state->synctype == 20) || (state->synctype == 24))
|
||||
{
|
||||
@@ -481,6 +499,12 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
||||
state->lastp25type = 1;
|
||||
sprintf (state->fsubtype, " LDU1 ");
|
||||
state->numtdulc = 0;
|
||||
if (state->payload_algid == 0x81)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
//LFSRP (state); //HERE HERE best placement?
|
||||
}
|
||||
|
||||
processLDU1 (opts, state);
|
||||
}
|
||||
else if (strcmp (duid, "22") == 0)
|
||||
|
||||
@@ -144,12 +144,15 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
* 32 = DMR MS Voice
|
||||
* 33 = DMR MS Data
|
||||
* 34 = DMR RC Data
|
||||
* 35 = +P25 P2
|
||||
* 36 = -P25 P2
|
||||
*/
|
||||
|
||||
|
||||
int i, j, t, o, dibit, sync, symbol, synctest_pos, lastt;
|
||||
char synctest[25];
|
||||
char synctest12[13]; //dPMR
|
||||
char synctest10[11];
|
||||
char synctest18[19];
|
||||
char synctest32[33];
|
||||
char synctest20[21]; //YSF
|
||||
@@ -269,6 +272,22 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
dibit = 51; // '3'
|
||||
}
|
||||
|
||||
//this is needed to capture dibits and convert them to appropriate format for a symbol bin
|
||||
if (opts->symbol_out == 1 && symbol != 0) //is 0 a valid symbol from dsd? //&& symbol != 0
|
||||
{
|
||||
int csymbol = 0;
|
||||
if (dibit == 49)
|
||||
{
|
||||
csymbol = 1; //1
|
||||
}
|
||||
if (dibit == 51)
|
||||
{
|
||||
csymbol = 3; //3
|
||||
}
|
||||
//fprintf (stderr, "%d", dibit);
|
||||
fputc (csymbol, opts->symbol_out_f);
|
||||
}
|
||||
|
||||
//digitize test for storing dibits in buffer correctly for dmr recovery
|
||||
|
||||
if (state->dmr_payload_p > state->dmr_payload_buf + 900000)
|
||||
@@ -597,6 +616,52 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
}
|
||||
//end YSF sync
|
||||
//P25 P2 sync
|
||||
strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right
|
||||
if(opts->frame_p25p2 == 1) //(opts->frame_ysf == 1
|
||||
{
|
||||
if (0 == 0) //opts->inverted_ysf == 0
|
||||
{
|
||||
if (strcmp(synctest20, P25P2_SYNC) == 0)
|
||||
{
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
fprintf (stderr, "\n+P25-P2 Sync");
|
||||
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 (35);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(opts->frame_p25p2 == 1) //(opts->frame_p25p2 == 1
|
||||
{
|
||||
if (0 == 0) //inverted p25
|
||||
{
|
||||
if (strcmp(synctest20, INV_P25P2_SYNC) == 0)
|
||||
{
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
fprintf (stderr, "\n-P25-P2 Sync");
|
||||
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 (36);
|
||||
}
|
||||
}
|
||||
}
|
||||
//dPMR sync
|
||||
strncpy(synctest, (synctest_p - 23), 24);
|
||||
strncpy(synctest12, (synctest_p - 11), 12);
|
||||
@@ -1093,6 +1158,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
|
||||
{
|
||||
strncpy (synctest18, (synctest_p - 17), 18);
|
||||
|
||||
455
src/dsd_main.c
455
src/dsd_main.c
@@ -43,20 +43,19 @@ int pretty_colors()
|
||||
|
||||
#include "p25p1_heuristics.h"
|
||||
#include "pa_devs.h"
|
||||
short int butt = 1;
|
||||
short int butt = 0;
|
||||
|
||||
char * FM_banner[9] = {
|
||||
" 2022 Dove Award Winner CTRL + C twice to exit",
|
||||
" ",
|
||||
" ██████╗ ██████╗██████╗ ███████╗███╗ ███╗███████╗",
|
||||
" ██╔══██╗██╔════╝██╔══██╗ ██╔════╝████╗ ████║██╔════╝",
|
||||
" ██║ ██║╚█████╗ ██║ ██║ █████╗ ██╔████╔██║█████╗ ",
|
||||
" ██║ ██║ ╚═══██╗██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
|
||||
" ██████╔╝██████╔╝██████╔╝ ██║ ██║ ╚═╝ ██║███████╗",
|
||||
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝",
|
||||
"https://github.com/lwvmobile/dsd-fme/tree/pulseaudio "
|
||||
" https://github.com/lwvmobile/dsd-fme/tree/pulseaudio "
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
comp (const void *a, const void *b)
|
||||
{
|
||||
@@ -74,6 +73,7 @@ struct stat st = {0};
|
||||
void
|
||||
noCarrier (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
// state->testcounter = 0;
|
||||
state->dibit_buf_p = state->dibit_buf + 200;
|
||||
memset (state->dibit_buf, 0, sizeof (int) * 200);
|
||||
//dmr buffer
|
||||
@@ -133,8 +133,6 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
||||
mbe_initMbeParms (state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2);
|
||||
|
||||
state->dmr_ms_mode = 0;
|
||||
state->dropL = 256; //drop it like its hot
|
||||
state->dropR = 256; //drop it like its hot
|
||||
|
||||
//not sure if desirable here or not just yet, may need to disable a few of these
|
||||
state->payload_mi = 0;
|
||||
@@ -145,12 +143,49 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
||||
state->payload_algidR = 0;
|
||||
state->payload_keyid = 0;
|
||||
state->payload_keyidR = 0;
|
||||
//just for a test
|
||||
if (state->M == 0)
|
||||
|
||||
state->payload_miN = 0;
|
||||
state->p25vc = 0;
|
||||
state->payload_miP = 0;
|
||||
|
||||
//initialize dmr data header source
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_source[1] = 0;
|
||||
|
||||
//initialize 12 rate superframe
|
||||
for (short i = 0; i < 288; i++)
|
||||
{
|
||||
state->K = 0;
|
||||
state->dmr_12_rate_sf[0][i] = 0;
|
||||
state->dmr_12_rate_sf[1][i] = 0;
|
||||
}
|
||||
|
||||
//initialize 34 rate superframe
|
||||
for (short i = 0; i < 288; i++)
|
||||
{
|
||||
state->dmr_34_rate_sf[0][i] = 0;
|
||||
state->dmr_34_rate_sf[1][i] = 0;
|
||||
}
|
||||
|
||||
//initialize data header bits
|
||||
state->data_header_blocks[0] = 1; //initialize with 1, otherwise we may end up segfaulting when no/bad data header
|
||||
state->data_header_blocks[1] = 1; //when trying to fill the superframe and 0-1 blocks give us an overflow
|
||||
state->data_header_padding[0] = 0;
|
||||
state->data_header_padding[1] = 0;
|
||||
state->data_header_format[0] = 0;
|
||||
state->data_header_format[1] = 0;
|
||||
state->data_header_sap[0] = 0;
|
||||
state->data_header_sap[1] = 0;
|
||||
state->data_block_counter[0] = 0;
|
||||
state->data_block_counter[1] = 0;
|
||||
state->data_p_head[0] = 0;
|
||||
state->data_p_head[1] = 0;
|
||||
|
||||
// state->dmr_so = 0; //let TLC or Voice LC/Burst zero or set this instead?
|
||||
// state->dmr_soR = 0;
|
||||
|
||||
state->dmr_encL = 0;
|
||||
state->dmr_encR = 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -172,15 +207,15 @@ initOpts (dsd_opts * opts)
|
||||
//sprintf (opts->audio_in_dev, "/dev/audio");
|
||||
sprintf (opts->audio_in_dev, "pulse");
|
||||
opts->audio_in_fd = -1;
|
||||
#ifdef USE_PORTAUDIO
|
||||
opts->audio_in_pa_stream = NULL;
|
||||
#endif
|
||||
// #ifdef USE_PORTAUDIO
|
||||
// opts->audio_in_pa_stream = NULL;
|
||||
// #endif
|
||||
//sprintf (opts->audio_out_dev, "/dev/audio");
|
||||
sprintf (opts->audio_out_dev, "pulse");
|
||||
opts->audio_out_fd = -1;
|
||||
#ifdef USE_PORTAUDIO
|
||||
opts->audio_out_pa_stream = NULL;
|
||||
#endif
|
||||
// #ifdef USE_PORTAUDIO
|
||||
// opts->audio_out_pa_stream = NULL;
|
||||
// #endif
|
||||
opts->split = 0;
|
||||
opts->playoffset = 0;
|
||||
opts->playoffsetR = 0;
|
||||
@@ -192,7 +227,16 @@ initOpts (dsd_opts * opts)
|
||||
opts->audio_gainR = 0;
|
||||
opts->audio_out = 1;
|
||||
opts->wav_out_file[0] = 0;
|
||||
opts->wav_out_fileR[0] = 0;
|
||||
opts->wav_out_file_raw[0] = 0;
|
||||
opts->symbol_out_file[0] = 0;
|
||||
opts->symbol_out_f = NULL;
|
||||
opts->symbol_out = 0;
|
||||
opts->wav_out_f = NULL;
|
||||
opts->wav_out_fR = NULL;
|
||||
opts->wav_out_raw = NULL;
|
||||
|
||||
opts->dmr_stereo_wav = 0; //flag for per call dmr stereo wav recordings
|
||||
//opts->wav_out_fd = -1;
|
||||
opts->serial_baud = 115200;
|
||||
sprintf (opts->serial_dev, "/dev/ttyUSB0");
|
||||
@@ -200,6 +244,7 @@ initOpts (dsd_opts * opts)
|
||||
opts->frame_dstar = 1;
|
||||
opts->frame_x2tdma = 1;
|
||||
opts->frame_p25p1 = 1;
|
||||
opts->frame_p25p2 = 0;
|
||||
opts->frame_nxdn48 = 0;
|
||||
opts->frame_nxdn96 = 0;
|
||||
opts->frame_dmr = 1;
|
||||
@@ -225,10 +270,11 @@ initOpts (dsd_opts * opts)
|
||||
opts->rtl_udp_port = 6020; //set UDP port for RTL remote
|
||||
opts->rtl_bandwidth = 12; //changed recommended default to 12, 24 for ProVoice
|
||||
opts->rtlsdr_ppm_error = 0; //initialize ppm with 0 value; bug reported by N.
|
||||
opts->rtl_started = 0;
|
||||
opts->pulse_raw_rate_in = 48000;
|
||||
opts->pulse_raw_rate_out = 48000; //doing tests with 2 channels at 24000 for 48000 audio default in pulse
|
||||
opts->pulse_raw_rate_out = 48000; //
|
||||
opts->pulse_digi_rate_in = 48000;
|
||||
opts->pulse_digi_rate_out = 48000; //need to copy this to rtl type in and change rate out to 8000
|
||||
opts->pulse_digi_rate_out = 8000; // reverted to 8/1, crisper sound, dmr stereo will switch to 24/2
|
||||
opts->pulse_raw_in_channels = 1;
|
||||
opts->pulse_raw_out_channels = 1;
|
||||
opts->pulse_digi_in_channels = 1; //2
|
||||
@@ -237,9 +283,9 @@ initOpts (dsd_opts * opts)
|
||||
sprintf (opts->output_name, "Auto Detect");
|
||||
opts->pulse_flush = 1; //set 0 to flush, 1 for flushed
|
||||
opts->use_ncurses_terminal = 0;
|
||||
opts->ncurses_compact = 0;
|
||||
opts->ncurses_history = 1;
|
||||
opts->payload = 0;
|
||||
|
||||
opts->EncryptionMode = MODE_UNENCRYPTED;
|
||||
opts->inverted_dpmr = 0;
|
||||
opts->dmr_stereo = 0;
|
||||
opts->aggressive_framesync = 1; //more aggressive to combat wonk wonk voice decoding
|
||||
@@ -247,6 +293,10 @@ initOpts (dsd_opts * opts)
|
||||
opts->audio_in_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
|
||||
opts->audio_out_type = 0; //this was never initialized, causes issues on rPI 64 (bullseye) if not initialized
|
||||
|
||||
opts->lrrp_file_output = 0;
|
||||
|
||||
opts->dmr_mute_encL = 1;
|
||||
opts->dmr_mute_encR = 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -255,6 +305,7 @@ initState (dsd_state * state)
|
||||
{
|
||||
|
||||
int i, j;
|
||||
// state->testcounter = 0;
|
||||
state->last_dibit = 0;
|
||||
state->dibit_buf = malloc (sizeof (int) * 1000000);
|
||||
state->dibit_buf_p = state->dibit_buf + 200;
|
||||
@@ -313,6 +364,7 @@ initState (dsd_state * state)
|
||||
sprintf (state->fsubtype, " ");
|
||||
sprintf (state->ftype, " ");
|
||||
state->symbolcnt = 0;
|
||||
state->symbolc = 0; //
|
||||
state->rf_mod = 0;
|
||||
state->numflips = 0;
|
||||
state->lastsynctype = -1;
|
||||
@@ -377,6 +429,7 @@ initState (dsd_state * state)
|
||||
state->nxdn_cipher_type = 0;
|
||||
state->nxdn_key = 0;
|
||||
sprintf (state->nxdn_call_type, " ");
|
||||
state->payload_miN = 0;
|
||||
|
||||
state->dpmr_color_code = -1;
|
||||
state->dpmr_caller_id = 0;
|
||||
@@ -419,7 +472,7 @@ initState (dsd_state * state)
|
||||
|
||||
state->K = 0;
|
||||
state->R = 0;
|
||||
state->M = 0;
|
||||
|
||||
state->dmr_stereo = 0;
|
||||
state->dmrburstL = 17; //initialize at higher value than possible
|
||||
state->dmrburstR = 17; //17 in char array is set for ERR
|
||||
@@ -429,11 +482,49 @@ initState (dsd_state * state)
|
||||
state->dmr_fidR = 0;
|
||||
state->dmr_ms_mode = 0;
|
||||
|
||||
state->dropL = 256; //drop it like its hot
|
||||
state->dropR = 256; //drop it like its hot
|
||||
state->p25vc = 0;
|
||||
|
||||
state->payload_miP = 0;
|
||||
|
||||
memset(state->dstarradioheader, 0, 41);
|
||||
|
||||
//initialize dmr data header source
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_source[1] = 0;
|
||||
|
||||
//initialize 12 rate superframe
|
||||
for (short i = 0; i < 288; i++)
|
||||
{
|
||||
state->dmr_12_rate_sf[0][i] = 0;
|
||||
state->dmr_12_rate_sf[1][i] = 0;
|
||||
}
|
||||
|
||||
//initialize 34 rate superframe
|
||||
for (short i = 0; i < 288; i++)
|
||||
{
|
||||
state->dmr_34_rate_sf[0][i] = 0;
|
||||
state->dmr_34_rate_sf[1][i] = 0;
|
||||
}
|
||||
|
||||
//initialize data header bits
|
||||
state->data_header_blocks[0] = 1; //initialize with 1, otherwise we may end up segfaulting when no/bad data header
|
||||
state->data_header_blocks[1] = 1; //when trying to fill the superframe and 0-1 blocks give us an overflow
|
||||
state->data_header_padding[0] = 0;
|
||||
state->data_header_padding[1] = 0;
|
||||
state->data_header_format[0] = 0;
|
||||
state->data_header_format[1] = 0;
|
||||
state->data_header_sap[0] = 0;
|
||||
state->data_header_sap[1] = 0;
|
||||
state->data_block_counter[0] = 0;
|
||||
state->data_block_counter[1] = 0;
|
||||
state->data_p_head[0] = 0;
|
||||
state->data_p_head[1] = 0;
|
||||
|
||||
state->menuopen = 0; //is the ncurses menu open, if so, don't process frame sync
|
||||
|
||||
state->dmr_encL = 0;
|
||||
state->dmr_encR = 0;
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
state->debug_sample_index = 0;
|
||||
state->debug_label_file = NULL;
|
||||
@@ -447,14 +538,15 @@ initState (dsd_state * state)
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
//printf ( "Github Build Version: %s \n", GIT_TAG);
|
||||
//printf ( "2022 Dove Award Recipient"); //Thanks, Scott
|
||||
|
||||
printf ("\n");
|
||||
printf ("Usage: dsd [options] Live scanner mode\n");
|
||||
printf (" or: dsd [options] -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
printf (" or: dsd -h Show help\n");
|
||||
printf ("Usage: dsd-fme [options] Live scanner mode\n");
|
||||
printf (" or: dsd-fme [options] -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
printf (" or: dsd-fme -h Show help\n");
|
||||
printf ("\n");
|
||||
printf ("Display Options:\n");
|
||||
printf (" -N Use NCurses Terminal\n");
|
||||
printf (" -use with 2> log.txt at end of command\n");
|
||||
printf (" -e Show Frame Info and errorbars (default)\n");
|
||||
printf (" -pe Show P25 encryption sync bits\n");
|
||||
printf (" -pl Show P25 link control bits\n");
|
||||
@@ -474,7 +566,7 @@ usage ()
|
||||
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
|
||||
printf (" -w <file> Output synthesized speech to a .wav file\n");
|
||||
//printf (" -a Display port audio devices\n");
|
||||
printf (" -W Monitor Source Audio When No Sync Detected (WIP!)\n");
|
||||
//printf (" -W Monitor Source Audio When No Sync Detected (WIP!)\n");
|
||||
printf ("\n");
|
||||
printf ("RTL-SDR options:\n");
|
||||
printf (" -c <hertz> RTL-SDR Frequency\n");
|
||||
@@ -495,43 +587,38 @@ usage ()
|
||||
printf (" -fa Auto-detect frame type (default)\n");
|
||||
printf (" -f1 Decode only P25 Phase 1\n");
|
||||
printf (" -fd Decode only D-STAR\n");
|
||||
printf (" -fr Decode only DMR/MOTOTRBO\n");
|
||||
printf (" -fr Decode only DMR\n");
|
||||
printf (" -fx Decode only X2-TDMA\n");
|
||||
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
|
||||
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
|
||||
printf (" -fp Decode only ProVoice*\n");
|
||||
printf (" -fm Decode only dPMR*\n");
|
||||
printf (" -l Disable DMR/MOTOTRBO and NXDN input filtering\n");
|
||||
printf (" -ma Auto-select modulation optimizations (default)\n");
|
||||
printf (" -mc Use only C4FM modulation optimizations\n");
|
||||
printf (" -mg Use only GFSK modulation optimizations\n");
|
||||
printf (" -mq Use only QPSK modulation optimizations\n");
|
||||
printf (" -l Disable DMR and NXDN input filtering\n");
|
||||
printf (" -pu Unmute Encrypted P25\n");
|
||||
printf (" -u <num> Unvoiced speech quality (default=3)\n");
|
||||
printf (" -xx Expect non-inverted X2-TDMA signal\n");
|
||||
printf (" -xr Expect inverted DMR/MOTOTRBO signal\n");
|
||||
printf (" -xr Expect inverted DMR signal\n");
|
||||
printf (" -xd Expect inverted ICOM dPMR signal\n"); //still need to do this
|
||||
printf ("\n");
|
||||
printf (" * denotes frame types that cannot be auto-detected.\n");
|
||||
printf ("\n");
|
||||
printf ("Advanced decoder options:\n");
|
||||
printf (" -A <num> QPSK modulation auto detection threshold (default=26)\n");
|
||||
printf ("Advanced Decoder options:\n");
|
||||
// printf (" -A <num> QPSK modulation auto detection threshold (default=26)\n");
|
||||
printf (" -S <num> Symbol buffer size for QPSK decision point tracking\n");
|
||||
printf (" (default=36)\n");
|
||||
printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n");
|
||||
printf (" (default=15)\n");
|
||||
printf (" -n Reset P25 Heuristics and initState variables on mixed signal decoding\n");
|
||||
printf (" Helps when decoding mixed signal types (P25P1) at same time\n");
|
||||
printf (" (WiP! May Cause Slow Memory Leak or System Hang - Experimental)\n");
|
||||
// printf (" -n Reset P25 Heuristics and initState variables on mixed signal decoding\n");
|
||||
// printf (" Helps when decoding mixed signal types (P25P1) at same time\n");
|
||||
// printf (" (WiP! May Cause Slow Memory Leak or System Hang - Experimental)\n");
|
||||
printf (" -T Enable DMR TDMA Stereo Voice (Two Slot Dual Voices)\n");
|
||||
printf (" This feature will open two streams for slot 1 voice and slot 2 voice\n");
|
||||
printf (" May Cause Skipping or sync issues if bad signal/errors\n");
|
||||
printf (" -F Enable DMR TDMA Stereo Passive Frame Sync\n");
|
||||
printf (" This feature will attempt to resync less often due to excessive voice errors\n");
|
||||
printf (" Use if skipping occurs, but may cause wonky audio due to loss of good sync\n");
|
||||
printf (" -Z Log MBE Payload to console\n");
|
||||
printf (" -Z Log MBE/Frame Payloads to console\n");
|
||||
printf ("\n");
|
||||
printf ("Report bugs to: https://github.com/lwvmobile/dsd-fme/issues \n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -539,8 +626,6 @@ void
|
||||
liveScanner (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
//still need this section mostly due the the crackling on the rtl dongle when upsampled
|
||||
//probably need to dig a little deeper, maybe inlvl releated?
|
||||
if (opts->audio_in_type == 1)
|
||||
{
|
||||
opts->pulse_digi_rate_out = 8000; //revert to 8K/1 for STDIN input, sometimes crackles when upsampling
|
||||
@@ -557,19 +642,6 @@ if (opts->audio_in_type == 1)
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_PORTAUDIO
|
||||
if(opts->audio_in_type == 2)
|
||||
{
|
||||
PaError err = Pa_StartStream( opts->audio_in_pa_stream );
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while starting the portaudio input stream\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_RTLSDR
|
||||
if(opts->audio_in_type == 3)
|
||||
{
|
||||
@@ -588,28 +660,38 @@ if (opts->audio_in_type == 1)
|
||||
opts->pulse_raw_out_channels = 1;
|
||||
|
||||
open_rtlsdr_stream(opts);
|
||||
opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opts->use_ncurses_terminal == 1)
|
||||
{
|
||||
ncursesOpen(opts, state);
|
||||
}
|
||||
|
||||
if (opts->audio_in_type == 0)
|
||||
{
|
||||
openPulseInput(opts);
|
||||
}
|
||||
|
||||
if (opts->audio_out_type == 0)
|
||||
{
|
||||
openPulseOutput(opts);
|
||||
}
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
noCarrier (opts, state);
|
||||
if (state->menuopen == 0)
|
||||
{
|
||||
state->synctype = getFrameSync (opts, state);
|
||||
// recalibrate center/umid/lmid
|
||||
state->center = ((state->max) + (state->min)) / 2;
|
||||
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
|
||||
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
|
||||
}
|
||||
|
||||
state->synctype = getFrameSync (opts, state);
|
||||
// recalibrate center/umid/lmid
|
||||
state->center = ((state->max) + (state->min)) / 2;
|
||||
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
|
||||
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
|
||||
|
||||
|
||||
while (state->synctype != -1)
|
||||
@@ -620,16 +702,24 @@ if (opts->audio_out_type == 0)
|
||||
state->debug_prefix = 'S';
|
||||
#endif
|
||||
|
||||
state->synctype = getFrameSync (opts, state);
|
||||
// state->synctype = getFrameSync (opts, state);
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
state->debug_prefix = '\0';
|
||||
#endif
|
||||
|
||||
// recalibrate center/umid/lmid
|
||||
state->center = ((state->max) + (state->min)) / 2;
|
||||
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
|
||||
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
|
||||
// // recalibrate center/umid/lmid
|
||||
// state->center = ((state->max) + (state->min)) / 2;
|
||||
// state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
|
||||
// state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
|
||||
if (state->menuopen == 0)
|
||||
{
|
||||
state->synctype = getFrameSync (opts, state);
|
||||
// recalibrate center/umid/lmid
|
||||
state->center = ((state->max) + (state->min)) / 2;
|
||||
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
|
||||
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -639,59 +729,33 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
noCarrier (opts, state);
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
closeWavOutFile (opts, state);
|
||||
}
|
||||
|
||||
#ifdef USE_PORTAUDIO
|
||||
if((opts->audio_in_type == 2) || (opts->audio_out_type == 2))
|
||||
{
|
||||
fprintf (stderr,"Terminating portaudio.\n");
|
||||
PaError err = paNoError;
|
||||
if(opts->audio_in_pa_stream != NULL)
|
||||
{
|
||||
err = Pa_CloseStream( opts->audio_in_pa_stream );
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while closing the portaudio input stream\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
}
|
||||
}
|
||||
if(opts->audio_out_pa_stream != NULL)
|
||||
{
|
||||
err = Pa_IsStreamActive( opts->audio_out_pa_stream );
|
||||
if(err == 1)
|
||||
err = Pa_StopStream( opts->audio_out_pa_stream );
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while closing the portaudio output stream\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
}
|
||||
err = Pa_CloseStream( opts->audio_out_pa_stream );
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while closing the portaudio output stream\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
}
|
||||
}
|
||||
err = Pa_Terminate();
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while terminating portaudio\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
{
|
||||
closeWavOutFile (opts, state);
|
||||
}
|
||||
if (opts->wav_out_raw != NULL)
|
||||
{
|
||||
closeWavOutFileRaw (opts, state);
|
||||
}
|
||||
if (opts->dmr_stereo_wav == 1)
|
||||
{
|
||||
closeWavOutFileL (opts, state);
|
||||
closeWavOutFileR (opts, state);
|
||||
}
|
||||
if (opts->symbol_out == 1)
|
||||
{
|
||||
closeSymbolOutFile (opts, state);
|
||||
}
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
closeMbeOutFile (opts, state);
|
||||
}
|
||||
|
||||
#ifdef USE_RTLSDR
|
||||
if(opts->audio_in_type == 3)
|
||||
{
|
||||
// TODO: cleanup demod threads
|
||||
cleanup_rtlsdr_stream();
|
||||
//temp disable to see if this corrects issues with closing
|
||||
//cleanup_rtlsdr_stream();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -775,15 +839,15 @@ main (int argc, char **argv)
|
||||
char versionstr[25];
|
||||
mbe_printVersion (versionstr);
|
||||
|
||||
|
||||
for (short int i = 0; i < 7; i++) {
|
||||
fprintf (stderr,"%s%s \n", FM_banner[i], KCYN); //cyan/blue text
|
||||
fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n");
|
||||
for (short int i = 1; i < 7; i++) {
|
||||
//fprintf (stderr,"%s%s \n", FM_banner[i], KGRN); //cyan/blue text
|
||||
fprintf (stderr,"%s\n", FM_banner[i]); //cyan/blue tex
|
||||
}
|
||||
fprintf (stderr,"%s", KNRM); //change back to normal
|
||||
fprintf (stderr, "%s \n", FM_banner[7]);
|
||||
fprintf (stderr,"Digital Speech Decoder: Florida Man Edition\n");
|
||||
//fprintf (stderr,"%s", KNRM); //change back to normal
|
||||
|
||||
fprintf (stderr, "Github Build Version: %s \n", GIT_TAG);
|
||||
fprintf (stderr,"mbelib version %s\n", versionstr);
|
||||
fprintf (stderr,"MBElib version %s\n", versionstr);
|
||||
|
||||
initOpts (&opts);
|
||||
initState (&state);
|
||||
@@ -793,7 +857,7 @@ main (int argc, char **argv)
|
||||
exitflag = 0;
|
||||
signal (SIGINT, sigfun);
|
||||
|
||||
while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:NWrlZTF")) != -1)
|
||||
while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:NQWrlZTF")) != -1)
|
||||
{
|
||||
opterr = 0;
|
||||
switch (c)
|
||||
@@ -802,7 +866,7 @@ main (int argc, char **argv)
|
||||
usage ();
|
||||
exit (0);
|
||||
case 'a':
|
||||
printPortAudioDevices();
|
||||
//printPortAudioDevices();
|
||||
exit(0);
|
||||
case 'e':
|
||||
opts.errorbars = 1;
|
||||
@@ -832,7 +896,8 @@ main (int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
sscanf (optarg, "%i", &opts.rtlsdr_ppm_error);
|
||||
//can't handle negative numbers?
|
||||
//sscanf (optarg, "%d", &opts.rtlsdr_ppm_error);
|
||||
break;
|
||||
case 'q':
|
||||
opts.errorbars = 0;
|
||||
@@ -858,15 +923,17 @@ main (int argc, char **argv)
|
||||
|
||||
case 'K':
|
||||
sscanf (optarg, "%lld", &state.K);
|
||||
state.M = 1;
|
||||
if (state.K > 256)
|
||||
{
|
||||
state.K = 256;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
sscanf (optarg, "%lld", &state.R);
|
||||
opts.dmr_mute_encL = 0;
|
||||
opts.dmr_mute_encR = 0;
|
||||
if (state.K == 1)
|
||||
{
|
||||
opts.dmr_mute_encL = 1;
|
||||
opts.dmr_mute_encR = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G': //Set rtl device gain
|
||||
@@ -877,11 +944,11 @@ main (int argc, char **argv)
|
||||
sscanf (optarg, "%d", &opts.rtl_squelch_level); //set squelch by user to prevent false positives on NXDN and others
|
||||
break;
|
||||
|
||||
case 'V': //Set rtl squelch level
|
||||
case 'V': //Set rtl voltage level
|
||||
sscanf (optarg, "%d", &opts.rtl_volume_multiplier); //set 'volume' multiplier for rtl-sdr samples
|
||||
break;
|
||||
|
||||
case 'U': //Set rtl squelch level
|
||||
case 'U': //Set rtl udp remote port
|
||||
sscanf (optarg, "%d", &opts.rtl_udp_port); //set udp port number for RTL remote
|
||||
break;
|
||||
|
||||
@@ -893,23 +960,20 @@ main (int argc, char **argv)
|
||||
sscanf (optarg, "%d", &opts.rtl_bandwidth);
|
||||
break;
|
||||
|
||||
case 'W': //monitor_input_audio if no sync
|
||||
opts.monitor_input_audio = 1;
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr,"Monitoring Source Audio when carrier present and No Sync Detected.\n");
|
||||
fprintf (stderr," - May cause Pulse Audio Server to crash on some systems.\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
opts.use_ncurses_terminal = 1;
|
||||
fprintf (stderr,"Enabling NCurses Terminal.\n");
|
||||
fprintf (stderr," - may need to issue 'reset' command in terminal after use\n");
|
||||
//fprintf (stderr," - may need to issue 'reset' command in terminal after use\n");
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
opts.payload = 1;
|
||||
fprintf (stderr,"Logging MBE Payload to console\n");
|
||||
fprintf (stderr,"Logging Frame Payload to console\n");
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
opts.lrrp_file_output = 1;
|
||||
fprintf (stderr,"Logging LRRP data to ~/lrrp.txt \n");
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
@@ -917,16 +981,18 @@ main (int argc, char **argv)
|
||||
state.dmr_stereo = 1; //this values toggles on and off depending on voice or data handling
|
||||
opts.pulse_digi_rate_out = 24000;
|
||||
opts.pulse_digi_out_channels = 2;
|
||||
fprintf (stderr, "%s", KRED);
|
||||
sprintf (opts.output_name, "DMR STEREO");
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr,"DMR Stereo Sync and Functionality Enabled.\n");
|
||||
fprintf (stderr,"DMR Stereo will disable WAV and MBE file saving!\n");
|
||||
fprintf (stderr,"DMR Stereo will disable MBE file saving!\n");
|
||||
fprintf (stderr,"DMR Stereo per call WAV file can be enabled in the NCurses Terminal!\n");
|
||||
fprintf (stderr,"Also consider using -F if playback is too choppy!\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
opts.aggressive_framesync = 0;
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
break;
|
||||
@@ -984,32 +1050,28 @@ main (int argc, char **argv)
|
||||
state.aout_gainR = opts.audio_gain;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
opts.reset_state = 1;
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr,"Enabling Automatic Reset of P25 states\n");
|
||||
//fprintf (stderr," -Helps with multiple signal type decoding\n");
|
||||
//fprintf (stderr," -(WiP! May cause slow memory leak)\n");
|
||||
fprintf (stderr," -(Disabled until memory leak issues can be resolved!)\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
strncpy(opts.wav_out_file, optarg, 1023);
|
||||
opts.wav_out_file[1023] = '\0';
|
||||
fprintf (stderr,"Writing + Appending audio to file %s\n", opts.wav_out_file);
|
||||
fprintf (stderr,"Writing + Appending decoded audio to file %s\n", opts.wav_out_file);
|
||||
openWavOutFile (&opts, &state);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
sscanf (optarg, "%d", &opts.serial_baud);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
strncpy(opts.serial_dev, optarg, 1023);
|
||||
opts.serial_dev[1023] = '\0';
|
||||
break;
|
||||
//case 'R':
|
||||
// sscanf (optarg, "%d", &opts.resume);
|
||||
// fprintf (stderr,"Enabling scan resume after %i TDULC frames\n", opts.resume);
|
||||
// break;
|
||||
|
||||
case 'R':
|
||||
sscanf (optarg, "%d", &opts.resume);
|
||||
fprintf (stderr,"Enabling scan resume after %i TDULC frames\n", opts.resume);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (optarg[0] == 'a')
|
||||
{
|
||||
@@ -1017,7 +1079,7 @@ main (int argc, char **argv)
|
||||
opts.frame_x2tdma = 1;
|
||||
opts.frame_p25p1 = 1;
|
||||
opts.frame_nxdn48 = 0;
|
||||
opts.frame_nxdn96 = 0; //causes false positives, leave on 0
|
||||
opts.frame_nxdn96 = 0;
|
||||
opts.frame_dmr = 1;
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
@@ -1033,6 +1095,7 @@ main (int argc, char **argv)
|
||||
opts.frame_dmr = 0;
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
state.rf_mod = 0;
|
||||
sprintf (opts.output_name, "D-STAR");
|
||||
fprintf (stderr,"Decoding only D-STAR frames.\n");
|
||||
}
|
||||
@@ -1104,7 +1167,6 @@ main (int argc, char **argv)
|
||||
opts.mod_gfsk = 0;
|
||||
state.rf_mod = 0;
|
||||
sprintf (opts.output_name, "NXDN48");
|
||||
//opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate
|
||||
fprintf (stderr,"Setting symbol rate to 2400 / second\n");
|
||||
fprintf (stderr,"Decoding only NXDN 4800 baud frames.\n");
|
||||
}
|
||||
@@ -1113,23 +1175,44 @@ main (int argc, char **argv)
|
||||
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_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 1;
|
||||
state.samplesPerSymbol = 10;
|
||||
//state.symbolCenter = 10;
|
||||
state.samplesPerSymbol = 20; //10
|
||||
state.symbolCenter = 10;
|
||||
opts.mod_c4fm = 1;
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0;
|
||||
state.rf_mod = 0;
|
||||
sprintf (opts.output_name, "YSF");
|
||||
//opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate
|
||||
fprintf (stderr,"Setting symbol rate to 2400 / second\n");
|
||||
fprintf (stderr,"Decoding only YSF frames.\nNot working yet!\n");
|
||||
}
|
||||
else if (optarg[0] == '2')
|
||||
{
|
||||
opts.frame_dstar = 0;
|
||||
opts.frame_x2tdma = 0;
|
||||
opts.frame_p25p1 = 0;
|
||||
opts.frame_p25p2 = 1;
|
||||
opts.frame_nxdn48 = 0;
|
||||
opts.frame_nxdn96 = 0;
|
||||
opts.frame_dmr = 0;
|
||||
opts.frame_dpmr = 0;
|
||||
opts.frame_provoice = 0;
|
||||
opts.frame_ysf = 0;
|
||||
state.samplesPerSymbol = 20; //10
|
||||
state.symbolCenter = 10;
|
||||
opts.mod_c4fm = 0;
|
||||
opts.mod_qpsk = 1;
|
||||
opts.mod_gfsk = 0;
|
||||
state.rf_mod = 0;
|
||||
sprintf (opts.output_name, "P25-P2");
|
||||
fprintf (stderr,"Decoding P25-P2 frames.\nNot working yet!\n");
|
||||
}
|
||||
else if (optarg[0] == 'n')
|
||||
{
|
||||
opts.frame_dstar = 0;
|
||||
@@ -1161,9 +1244,9 @@ main (int argc, char **argv)
|
||||
opts.mod_qpsk = 0;
|
||||
opts.mod_gfsk = 0; //
|
||||
state.rf_mod = 0; //
|
||||
sprintf (opts.output_name, "DMR/MOTOTRBO");
|
||||
sprintf (opts.output_name, "DMR LEH");
|
||||
//fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
|
||||
fprintf (stderr,"Decoding only DMR/MOTOTRBO frames.\n");
|
||||
fprintf (stderr,"Decoding only DMR frames.\n");
|
||||
}
|
||||
else if (optarg[0] == 'm')
|
||||
{
|
||||
@@ -1242,7 +1325,7 @@ main (int argc, char **argv)
|
||||
else if (optarg[0] == 'r')
|
||||
{
|
||||
opts.inverted_dmr = 1;
|
||||
fprintf (stderr,"Expecting inverted DMR/MOTOTRBO signals.\n");
|
||||
fprintf (stderr,"Expecting inverted DMR signals.\n");
|
||||
}
|
||||
else if (optarg[0] == 'd')
|
||||
{
|
||||
@@ -1253,7 +1336,6 @@ main (int argc, char **argv)
|
||||
case 'A':
|
||||
sscanf (optarg, "%i", &opts.mod_threshold);
|
||||
fprintf (stderr,"Setting C4FM/QPSK auto detection threshold to %i\n", opts.mod_threshold);
|
||||
break;
|
||||
case 'S':
|
||||
sscanf (optarg, "%i", &opts.ssize);
|
||||
if (opts.ssize > 128)
|
||||
@@ -1294,11 +1376,6 @@ main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.use_ncurses_terminal == 1)
|
||||
{
|
||||
ncursesOpen();
|
||||
}
|
||||
|
||||
if (opts.resume > 0)
|
||||
{
|
||||
openSerial (&opts, &state);
|
||||
@@ -1314,23 +1391,7 @@ main (int argc, char **argv)
|
||||
opts.audio_out_type == 0;
|
||||
}
|
||||
|
||||
#ifdef USE_PORTAUDIO
|
||||
if((strncmp(opts.audio_in_dev, "pa:", 3) == 0)
|
||||
|| (strncmp(opts.audio_out_dev, "pa:", 3) == 0))
|
||||
{
|
||||
fprintf (stderr,"Initializing portaudio.\n");
|
||||
PaError err = Pa_Initialize();
|
||||
if( err != paNoError )
|
||||
{
|
||||
//fprintf (stderr, "An error occured while initializing portaudio\n" );
|
||||
//fprintf (stderr, "Error number: %d\n", err );
|
||||
//fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
exit(err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opts.playfiles == 1)
|
||||
if (opts.playfiles == 1)
|
||||
{
|
||||
opts.split = 1;
|
||||
opts.playoffset = 0;
|
||||
@@ -1345,7 +1406,7 @@ main (int argc, char **argv)
|
||||
openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
|
||||
}
|
||||
}
|
||||
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
|
||||
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
|
||||
{
|
||||
opts.split = 1;
|
||||
opts.playoffset = 0;
|
||||
@@ -1368,16 +1429,15 @@ main (int argc, char **argv)
|
||||
else
|
||||
{
|
||||
opts.split = 0;
|
||||
opts.playoffset = 25; // 38
|
||||
opts.playoffsetR = 25; // 38
|
||||
opts.playoffset = 25;
|
||||
opts.playoffsetR = 25;
|
||||
opts.delay = 0;
|
||||
openAudioInDevice (&opts); //disabled all four instances of openAudio devices, in and out for now
|
||||
openAudioInDevice (&opts);
|
||||
opts.audio_out_fd = opts.audio_in_fd;
|
||||
}
|
||||
|
||||
if (opts.playfiles == 1)
|
||||
{
|
||||
//need set to 8000/1 for amb/imb playback, upsampling seems to cause random crackling
|
||||
opts.pulse_digi_rate_out = 8000;
|
||||
opts.pulse_digi_out_channels = 1;
|
||||
openPulseOutput(&opts); //need to open it up for output
|
||||
@@ -1389,9 +1449,6 @@ main (int argc, char **argv)
|
||||
liveScanner (&opts, &state);
|
||||
}
|
||||
|
||||
if (opts.use_ncurses_terminal == 1){
|
||||
//ncursesClose ();
|
||||
}
|
||||
cleanupAndExit (&opts, &state);
|
||||
|
||||
return (0);
|
||||
|
||||
171
src/dsd_mbe.c
171
src/dsd_mbe.c
@@ -17,10 +17,6 @@
|
||||
|
||||
#include "dsd.h"
|
||||
|
||||
//
|
||||
//C
|
||||
//
|
||||
|
||||
void
|
||||
playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
|
||||
{
|
||||
@@ -117,8 +113,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
};
|
||||
//
|
||||
|
||||
|
||||
int i;
|
||||
int i;
|
||||
char imbe_d[88];
|
||||
char ambe_d[49];
|
||||
char ambe_d_str[50];
|
||||
@@ -141,20 +136,44 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
{
|
||||
// 0 +P25p1
|
||||
// 1 -P25p1
|
||||
state->errs = mbe_eccImbe7200x4400C0 (imbe_fr);
|
||||
state->errs2 = state->errs;
|
||||
mbe_demodulateImbe7200x4400Data (imbe_fr);
|
||||
state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
|
||||
|
||||
mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
|
||||
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
//mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
PrintIMBEData (opts, state, imbe_d);
|
||||
}
|
||||
|
||||
//increment vc counter by one.
|
||||
state->p25vc++;
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveImbe4400Data (opts, state, imbe_d);
|
||||
}
|
||||
}
|
||||
else if ((state->synctype == 14) || (state->synctype == 15))
|
||||
else if ((state->synctype == 14) || (state->synctype == 15)) //pV Sync
|
||||
{
|
||||
mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
state->errs = mbe_eccImbe7100x4400C0 (imbe7100_fr);
|
||||
state->errs2 = state->errs;
|
||||
mbe_demodulateImbe7100x4400Data (imbe7100_fr);
|
||||
state->errs2 += mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d);
|
||||
mbe_convertImbe7100to7200(imbe_d); //needs extra conversion step apparently
|
||||
|
||||
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
//below line the old way of doing this
|
||||
// mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
PrintIMBEData (opts, state, imbe_d);
|
||||
@@ -176,6 +195,28 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
saveAmbe2450Data (opts, state, ambe_d);
|
||||
}
|
||||
}
|
||||
else if ((state->synctype == 8) || (state->synctype == 9))
|
||||
{
|
||||
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
||||
state->errs2 = state->errs;
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
|
||||
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
PrintAMBEData (opts, state, ambe_d);
|
||||
}
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveAmbe2450Data (opts, state, ambe_d);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//stereo slots and slot 0 (left slot)
|
||||
@@ -186,28 +227,26 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
state->errs2 = state->errs;
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
//
|
||||
//F
|
||||
//
|
||||
|
||||
//
|
||||
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) //
|
||||
{
|
||||
k = BP[state->K];
|
||||
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
||||
for (short int j = 0; j < 49; j++)
|
||||
for (short int j = 0; j < 48; j++) //49
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
}
|
||||
//
|
||||
//D
|
||||
//
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
|
||||
//old method for this step below
|
||||
//mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
if (opts->payload == 1)
|
||||
if (opts->payload == 1) // && state->R == 0 this is why slot 1 didn't primt abme, probably had it set during testing
|
||||
{
|
||||
PrintAMBEData (opts, state, ambe_d);
|
||||
}
|
||||
@@ -220,24 +259,21 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
state->errs2R = state->errsR;
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
//
|
||||
//G
|
||||
//
|
||||
|
||||
//BP Handling, Slot 2
|
||||
if (state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0) //
|
||||
{
|
||||
k = BP[state->K];
|
||||
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
||||
for (short int j = 0; j < 49; j++)
|
||||
for (short int j = 0; j < 48; j++)
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
}
|
||||
//
|
||||
//E
|
||||
//
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR,
|
||||
ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
|
||||
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR,
|
||||
ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
|
||||
|
||||
//old method for this step below
|
||||
//mbe_processAmbe3600x2450Framef (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR, ambe_fr, ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
|
||||
@@ -246,7 +282,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
PrintAMBEData (opts, state, ambe_d);
|
||||
}
|
||||
}
|
||||
//if using older DMR method, dPMR, or NXDN
|
||||
|
||||
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
||||
if (opts->dmr_stereo == 0)
|
||||
{
|
||||
mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
@@ -254,7 +291,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
{
|
||||
PrintAMBEData (opts, state, ambe_d);
|
||||
}
|
||||
if (opts->mbe_out_f != NULL)
|
||||
//only save MBE files if not enc or unmuted, THIS does not seem to work for some reason
|
||||
if (opts->mbe_out_f != NULL && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) )
|
||||
{
|
||||
saveAmbe2450Data (opts, state, ambe_d);
|
||||
}
|
||||
@@ -263,35 +301,88 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
|
||||
}
|
||||
|
||||
state->debug_audio_errors += state->errs2;
|
||||
state->debug_audio_errorsR += state->errs2R;
|
||||
//having these values here I think caused muddy audio, seems cleaner now when moved to correct area
|
||||
// state->debug_audio_errors += state->errs2;
|
||||
// state->debug_audio_errorsR += state->errs2R;
|
||||
|
||||
//quick enc check to determine whether or not to play enc traffic
|
||||
int enc_bit = 0;
|
||||
//end enc check
|
||||
|
||||
if (opts->dmr_stereo == 1 && state->currentslot == 0)
|
||||
{
|
||||
processAudio (opts, state);
|
||||
if (opts->audio_out == 1)
|
||||
enc_bit = (state->dmr_so >> 6) & 0x1;
|
||||
if (enc_bit == 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
state->dmr_encL = 1;
|
||||
}
|
||||
else state->dmr_encL = 0;
|
||||
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
||||
{
|
||||
state->debug_audio_errors += state->errs2;
|
||||
processAudio (opts, state);
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts->dmr_stereo == 1 && state->currentslot == 1)
|
||||
{
|
||||
processAudioR (opts, state);
|
||||
if (opts->audio_out == 1)
|
||||
enc_bit = (state->dmr_soR >> 6) & 0x1;
|
||||
if (enc_bit == 0x1)
|
||||
{
|
||||
playSynthesizedVoiceR (opts, state);
|
||||
state->dmr_encR = 1;
|
||||
}
|
||||
else state->dmr_encR = 0;
|
||||
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
||||
{
|
||||
state->debug_audio_errorsR += state->errs2R;
|
||||
processAudioR (opts, state);
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
playSynthesizedVoiceR (opts, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opts->dmr_stereo == 0)
|
||||
|
||||
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
||||
if (opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) )
|
||||
{
|
||||
state->debug_audio_errors += state->errs2;
|
||||
processAudio (opts, state);
|
||||
if (opts->audio_out == 1)
|
||||
{
|
||||
playSynthesizedVoice (opts, state);
|
||||
}
|
||||
}
|
||||
if (opts->wav_out_f != NULL && opts->dmr_stereo == 0)
|
||||
|
||||
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
||||
if (opts->wav_out_f != NULL && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0))
|
||||
{
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
|
||||
//per call can only be used when ncurses terminal is active since we use its call history matrix for when to record
|
||||
if (opts->use_ncurses_terminal == 1 && opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 0)
|
||||
{
|
||||
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
||||
{
|
||||
//write wav to per call on left channel Slot 1
|
||||
writeSynthesizedVoice (opts, state);
|
||||
}
|
||||
}
|
||||
|
||||
//per call can only be used when ncurses terminal is active since we use its call history matrix for when to record
|
||||
if (opts->use_ncurses_terminal == 1 && opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 1)
|
||||
{
|
||||
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
||||
{
|
||||
//write wav to per call on right channel Slot 2
|
||||
writeSynthesizedVoiceR (opts, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
1364
src/dsd_ncurses.c
1364
src/dsd_ncurses.c
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,9 @@ resetState (dsd_state * state)
|
||||
|
||||
int i, j;
|
||||
|
||||
state->dibit_buf = malloc (sizeof (int) * 1000000);
|
||||
state->dibit_buf_p = state->dibit_buf + 200;
|
||||
memset (state->dibit_buf, 0, sizeof (int) * 200);
|
||||
// state->dibit_buf = malloc (sizeof (int) * 1000000);
|
||||
// state->dibit_buf_p = state->dibit_buf + 200;
|
||||
// memset (state->dibit_buf, 0, sizeof (int) * 200);
|
||||
state->repeat = 0; //not sure yet
|
||||
//state->audio_out_buf = malloc (sizeof (short) * 1000000);
|
||||
//memset (state->audio_out_buf, 0, 100 * sizeof (short));
|
||||
@@ -95,6 +95,10 @@ resetState (dsd_state * state)
|
||||
state->debug_header_critical_errors = 0;
|
||||
|
||||
state->nxdn_last_ran = 0;
|
||||
// state->payload_algid = 0;
|
||||
// state->payload_algidR = 0;
|
||||
state->dmr_encL = 0;
|
||||
state->dmr_encR = 0;
|
||||
|
||||
//each time you run this, it increses memory use by 4MB, massive memory leak
|
||||
//need to revisit this sometime and look into only resetting only the necesary items to let P25 switch between signals (C4FM or Wide) without needing a restart
|
||||
|
||||
@@ -26,6 +26,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
|
||||
sum = 0;
|
||||
count = 0;
|
||||
sample = 0; //init sample with a value of 0...see if this was causing issues with raw audio monitoring
|
||||
|
||||
for (i = 0; i < state->samplesPerSymbol; i++) //right HERE
|
||||
{
|
||||
@@ -81,15 +82,22 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
}
|
||||
|
||||
// Read the new sample from the input
|
||||
if(opts->audio_in_type == 0)
|
||||
if(opts->audio_in_type == 0) // && state->menuopen == 0 still not quite working
|
||||
{
|
||||
pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL );
|
||||
//look into how processAudio handles playback, not sure if latency issues, or garbage sample values crash pulse when written
|
||||
if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample < 32767 && sample > -32767)
|
||||
// if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample < 32767 && sample > -32767)
|
||||
if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample != 0)
|
||||
{
|
||||
state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here?
|
||||
pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL);
|
||||
}
|
||||
//playback is wrong, depends on samples_per_symbol, maybe make a buffer and store first?
|
||||
//making buffer might also fix raw audio monitoring as well
|
||||
if (opts->wav_out_file_raw[0] != 0) //if set for recording sample raw files
|
||||
{
|
||||
//writeRawSample (opts, state, sample);
|
||||
}
|
||||
|
||||
}
|
||||
else if (opts->audio_in_type == 1) {
|
||||
@@ -122,7 +130,8 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
{
|
||||
#ifdef USE_RTLSDR
|
||||
// TODO: need to read demodulated stream here
|
||||
get_rtlsdr_sample(&sample);
|
||||
// get_rtlsdr_sample(&sample);
|
||||
get_rtlsdr_sample(&sample, opts, state);
|
||||
if (opts->monitor_input_audio == 1 && state->lastsynctype == -1 && sample < 32767 && sample > -32767)
|
||||
{
|
||||
state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here?
|
||||
@@ -131,6 +140,11 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
|
||||
#endif
|
||||
}
|
||||
// //test reading symbol bin files
|
||||
// else if (opts->audio_in_type == 4)
|
||||
// {
|
||||
// //use fopen and read in a sample, check boatbod op25 for clues
|
||||
// }
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
state->debug_sample_index++;
|
||||
@@ -338,6 +352,73 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
}
|
||||
#endif
|
||||
|
||||
//read op25/fme symbol bin files
|
||||
if (opts->audio_in_type == 4)
|
||||
{
|
||||
//use fopen and read in a symbol, check op25 for clues
|
||||
if(opts->symbolfile == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error Opening File %s\n", opts->symbolfile);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
state->symbolc = fgetc(opts->symbolfile);
|
||||
//fprintf(stderr, "%d", state->symbolc);
|
||||
if( feof(opts->symbolfile) )
|
||||
{
|
||||
opts->audio_in_type = 0; //switch to pulse after playback, ncurses terminal can initiate replay if wanted
|
||||
fclose(opts->symbolfile);
|
||||
openPulseInput(opts);
|
||||
}
|
||||
|
||||
//flipping these to 'positive' produces terrible results in P25 P1, and I tried flopping it every way I could
|
||||
//positive polarity works fine with DMR, but not P25, so may look at reading and storing based on frame type?
|
||||
if (opts->frame_p25p1 == 1) //use inverted polarity for reading P25, but not DMR (or others?)
|
||||
{
|
||||
if (state->symbolc == 0)
|
||||
{
|
||||
symbol = -1; //-1
|
||||
}
|
||||
if (state->symbolc == 1)
|
||||
{
|
||||
symbol = -3; //-3
|
||||
}
|
||||
if (state->symbolc == 2)
|
||||
{
|
||||
symbol = 1; //1
|
||||
}
|
||||
if (state->symbolc == 3)
|
||||
{
|
||||
symbol = 3; //3
|
||||
}
|
||||
}
|
||||
else if (opts->frame_provoice == 1) //syncs fine, but issues with dibit reading
|
||||
{
|
||||
//provoice has issue where sync is okay, but decode isn't working after sync
|
||||
//symbol = state->symbolc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state->symbolc == 0)
|
||||
{
|
||||
symbol = 1; //-1
|
||||
}
|
||||
if (state->symbolc == 1)
|
||||
{
|
||||
symbol = 3; //-3
|
||||
}
|
||||
if (state->symbolc == 2)
|
||||
{
|
||||
symbol = -1; //1
|
||||
}
|
||||
if (state->symbolc == 3)
|
||||
{
|
||||
symbol = -3; //3
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
state->symbolcnt++;
|
||||
return (symbol);
|
||||
|
||||
@@ -1224,10 +1224,11 @@ void Golay_24_12_encode(unsigned char *origBits, unsigned char *encodedBits)
|
||||
encodedBits[j] += origBits[i] * Golay_24_12_m_G[24*i + j];
|
||||
}
|
||||
}
|
||||
|
||||
// fprintf (stderr, "\n Inside Golay - Encoded Bits = "); //disable later on
|
||||
for (i = 0; i < 24; i++)
|
||||
{
|
||||
encodedBits[i] %= 2;
|
||||
// fprintf (stderr, "%b", encodedBits[i]); //disable later on
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "dsd.h"
|
||||
#include "nxdn_const.h"
|
||||
|
||||
//don't know why this doesn't work right in LEH, need to figure that out for him
|
||||
//works just fien when ripped from his and into mine
|
||||
//must be some random thing, I'll look at his when I have a chance
|
||||
void processNXDNData (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int i, dibit = 0;
|
||||
@@ -24,7 +21,7 @@ void processNXDNData (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
|
||||
/* Start pseudo-random NXDN sequence after
|
||||
* LITCH = 16 bit = 8 dibit
|
||||
* LICH = 16 bit = 8 dibit
|
||||
* ==> Index 8 */
|
||||
pr = (unsigned char *)(&nxdnpr2[8]);
|
||||
for (i = 0; i < 30; i++)
|
||||
|
||||
741
src/nxdn_lib.c
741
src/nxdn_lib.c
@@ -60,13 +60,13 @@
|
||||
} /* End ConvertBitIntoBytes() */
|
||||
|
||||
|
||||
uint8_t NXDN_decode_LICH(uint8_t InputLich[8],
|
||||
uint8_t * RFChannelType,
|
||||
uint8_t * FunctionnalChannelType,
|
||||
uint8_t * Option,
|
||||
uint8_t * Direction,
|
||||
uint8_t * CompleteLichBinaryFormat,
|
||||
uint8_t Inverted)
|
||||
uint8_t NXDN_decode_LICH(uint8_t InputLich[8],
|
||||
uint8_t * RFChannelType,
|
||||
uint8_t * FunctionnalChannelType,
|
||||
uint8_t * Option,
|
||||
uint8_t * Direction,
|
||||
uint8_t * CompleteLichBinaryFormat,
|
||||
uint8_t Inverted)
|
||||
{
|
||||
uint8_t GoodParity = 0;
|
||||
uint32_t i;
|
||||
@@ -294,6 +294,7 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
|
||||
|
||||
/* Check CRC */
|
||||
if(state->NxdnSacchRawPart[i].CrcIsGood == 0) CrcCorrect = 0;
|
||||
//fprintf(stderr, "\n SAACH P# %1d - %05X", i, state->NxdnSacchRawPart[i].Data);
|
||||
}
|
||||
|
||||
/* Decodes the element content */
|
||||
@@ -553,7 +554,7 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
|
||||
uint32_t i;
|
||||
uint8_t MessageType;
|
||||
uint64_t CurrentIV = 0;
|
||||
|
||||
unsigned long long int FullMessage = 0;
|
||||
/* Get the "Message Type" field */
|
||||
MessageType = (ElementsContent[2] & 1) << 5;
|
||||
MessageType |= (ElementsContent[3] & 1) << 4;
|
||||
@@ -562,6 +563,8 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
|
||||
MessageType |= (ElementsContent[6] & 1) << 1;
|
||||
MessageType |= (ElementsContent[7] & 1) << 0;
|
||||
|
||||
//fprintf(stderr, "\nMessage Type = %X ", MessageType);
|
||||
|
||||
/* Save the "F1" and "F2" flags */
|
||||
state->NxdnElementsContent.F1 = ElementsContent[0];
|
||||
state->NxdnElementsContent.F2 = ElementsContent[1];
|
||||
@@ -569,7 +572,16 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state,
|
||||
/* Save the "Message Type" field */
|
||||
state->NxdnElementsContent.MessageType = MessageType;
|
||||
|
||||
//fprintf(stderr, "Message Type = 0x%02X ", MessageType & 0xFF);
|
||||
//fprintf(stderr, "\n Message Type = 0x%02X ", MessageType & 0xFF);
|
||||
|
||||
//Dump the Message into a HEX value for vieweing
|
||||
//FullMessage = (unsigned long long int)ConvertBitIntoBytes(&Message[0], 64);
|
||||
for (short int i = 0; i < 64; i++)
|
||||
{
|
||||
FullMessage = FullMessage << 1;
|
||||
FullMessage |= ElementsContent[i];
|
||||
}
|
||||
//fprintf(stderr, "\nFull Message = %016llX ", FullMessage);
|
||||
|
||||
/* Decode the right "Message Type" */
|
||||
switch(MessageType)
|
||||
@@ -666,6 +678,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
uint8_t KeyID = 0;
|
||||
uint8_t DuplexMode[32] = {0};
|
||||
uint8_t TransmissionMode[32] = {0};
|
||||
unsigned long long int FullMessage = 0;
|
||||
|
||||
//UNUSED_VARIABLE(opts);
|
||||
//UNUSED_VARIABLE(state);
|
||||
@@ -712,14 +725,14 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
if(CCOption & 0x40) fprintf(stderr, "Visitor ");
|
||||
if(CCOption & 0x20) fprintf(stderr, "Priority Paging ");
|
||||
|
||||
/* On an AES or DES encrypted frame one IV is used on two
|
||||
* superframe.
|
||||
* The first superframe contains a VCALL message inside
|
||||
* the SACCH and the second superframe contains the next IV
|
||||
* to use.
|
||||
*
|
||||
* Set the correct part of encrypted frame flag.
|
||||
*/
|
||||
//Dump the Message into a HEX value for vieweing
|
||||
//FullMessage = (unsigned long long int)ConvertBitIntoBytes(&Message[0], 64);
|
||||
// for (short int i = 0; i < 64; i++)
|
||||
// {
|
||||
// FullMessage = FullMessage << 1;
|
||||
// FullMessage |= Message[i];
|
||||
// }
|
||||
|
||||
if((CipherType == 2) || (CipherType == 3))
|
||||
{
|
||||
state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 1;
|
||||
@@ -742,11 +755,17 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
NXDN_Voice_Call_Option_To_Str(VoiceCallOption, DuplexMode, TransmissionMode);
|
||||
fprintf(stderr, "%s %s - ", DuplexMode, TransmissionMode);
|
||||
|
||||
/* Print Source ID and Destination ID (Talk Group or Unit ID) */
|
||||
//fprintf (stderr, "%s", KGRN);
|
||||
fprintf(stderr, "Src=%u - Dst/TG=%u ", SourceUnitID & 0xFFFF, DestinationID & 0xFFFF);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//state->nxdn_key = (KeyID & 0xFF);
|
||||
//state->nxdn_cipher_type = CipherType;
|
||||
/* Print the "Cipher Type" */
|
||||
if(CipherType != 0)
|
||||
{
|
||||
fprintf (stderr, "\n %s", KYEL);
|
||||
fprintf(stderr, "%s - ", NXDN_Cipher_Type_To_Str(CipherType));
|
||||
//state->nxdn_cipher_type = CipherType;
|
||||
}
|
||||
@@ -754,18 +773,12 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
/* Print the Key ID */
|
||||
if(CipherType != 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
|
||||
fprintf(stderr, "Key ID %u - ", KeyID & 0xFF);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
//fprintf (stderr, "%s", KNRM);
|
||||
//state->nxdn_key = (KeyID & 0xFF);
|
||||
}
|
||||
|
||||
/* Print Source ID and Destination ID (Talk Group or Unit ID) */
|
||||
|
||||
fprintf(stderr, "Src=%u - Dst/TG=%u ", SourceUnitID & 0xFFFF, DestinationID & 0xFFFF);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
|
||||
if(state->NxdnElementsContent.VCallCrcIsGood)
|
||||
{
|
||||
if ( (SourceUnitID & 0xFFFF) > 0 )
|
||||
@@ -773,10 +786,19 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
state->nxdn_last_rid = SourceUnitID & 0xFFFF; //only grab if CRC is okay
|
||||
state->nxdn_last_tg = (DestinationID & 0xFFFF);
|
||||
state->nxdn_key = (KeyID & 0xFF);
|
||||
state->nxdn_cipher_type = CipherType;
|
||||
state->nxdn_cipher_type = CipherType; //will this set to zero if no enc?
|
||||
}
|
||||
//fprintf(stderr, "(CRC OK) ");
|
||||
}
|
||||
//set enc bit here so we can tell playSynthesizedVoice whether or not to play enc traffic
|
||||
if (state->nxdn_cipher_type != 0)
|
||||
{
|
||||
state->dmr_encL = 1;
|
||||
}
|
||||
if (state->nxdn_cipher_type == 0)
|
||||
{
|
||||
state->dmr_encL = 0;
|
||||
}
|
||||
//fprintf(stderr, " (OK) - ");
|
||||
else
|
||||
{
|
||||
@@ -784,7 +806,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
fprintf(stderr, "(CRC ERR) ");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "\nFull Message = %016llX ", FullMessage);
|
||||
} /* End NXDN_decode_VCALL() */
|
||||
|
||||
|
||||
@@ -815,21 +837,15 @@ void NXDN_decode_VCALL_IV(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
*
|
||||
* Message[8..71] contains : The 64 bits IV
|
||||
*/
|
||||
|
||||
state->payload_miN = 0; //zero out
|
||||
/* Extract the IV from the VCALL_IV message */
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
state->NxdnElementsContent.IV[i] = (uint8_t)ConvertBitIntoBytes(&Message[(i + 1) * 8], 8);
|
||||
|
||||
state->payload_miN = state->payload_miN << 8 | state->NxdnElementsContent.IV[i];
|
||||
}
|
||||
|
||||
/* On an AES or DES encrypted frame one IV is used on two
|
||||
* superframe.
|
||||
* The first superframe contains a VCALL message inside
|
||||
* the SACCH and the second superframe contains the next IV
|
||||
* to use.
|
||||
*
|
||||
* Set the correct part of encrypted frame flag.
|
||||
*/
|
||||
state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 2;
|
||||
state->NxdnElementsContent.PartOfNextEncryptedFrame = 1;
|
||||
|
||||
@@ -1012,35 +1028,640 @@ uint8_t CRC6BitNXDN(uint8_t * BufferIn, uint32_t BitLength)
|
||||
return CRC;
|
||||
} /* End CRC6BitNXDN() */
|
||||
|
||||
|
||||
/* Scrambler used for NXDN transmission (different of the
|
||||
* voice encryption scrambler), see NXDN Part1-A Common Air Interface chapter
|
||||
* 4.6 for the polynomial description.
|
||||
* It is a X^9 + X^4 + 1 polynomial used as pseudo-random generator */
|
||||
void ScrambledNXDNVoiceBit(int * LfsrValue, char * BufferIn, char * BufferOut, int NbOfBitToScramble)
|
||||
//NXDN IDLE
|
||||
void ProcessNXDNIdleData (dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t LFSR;
|
||||
uint8_t bit;
|
||||
int i, dibit = 0;
|
||||
unsigned char sacch_raw[72] = {0};
|
||||
unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */
|
||||
unsigned char *pr;
|
||||
uint8_t CrcIsGood = 0;
|
||||
uint8_t StructureField = 0;
|
||||
uint8_t RAN = 0;
|
||||
uint8_t PartOfFrame = 0;
|
||||
|
||||
/* Load the initial LFSR value
|
||||
* LFSR = 0x0E4 at starting value */
|
||||
LFSR = (uint32_t)*LfsrValue;
|
||||
|
||||
for(i = 0; i < (uint32_t)NbOfBitToScramble; i++)
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
/* Bit 0 of LFSR is used to scramble data */
|
||||
BufferOut[i] = (BufferIn[i] ^ (LFSR & 1)) & 1;
|
||||
|
||||
/* Compute bit = X^0 + X^4 */
|
||||
bit = ((LFSR & 1) ^ ((LFSR >> 4) & 1)) & 1;
|
||||
|
||||
/* Insert bit on the 9th bit (X^9) */
|
||||
LFSR = ((LFSR >> 1) & 0xFF) | ((bit << 8) & 0x100);
|
||||
fprintf(stderr, "DATA - ");
|
||||
}
|
||||
|
||||
*LfsrValue = (int)LFSR;
|
||||
} /* End ScrambledNXDNVoiceBit() */
|
||||
/* Start pseudo-random NXDN sequence after
|
||||
* LICH = 16 bit = 8 dibit
|
||||
* ==> Index 8 */
|
||||
pr = (unsigned char *)(&nxdnpr[8]);
|
||||
for (i = 0; i < 30; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
|
||||
/* Store and de-interleave directly SACCH bits */
|
||||
sacch_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1
|
||||
sacch_raw[(2*i)+1] = (1 & dibit); // bit 0
|
||||
pr++;
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, "%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, " ");
|
||||
#endif
|
||||
|
||||
|
||||
/* Decode the SACCH fields */
|
||||
CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded);
|
||||
StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */
|
||||
RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */
|
||||
|
||||
/* Compute the Part of Frame according to the structure field */
|
||||
if (StructureField == 3) PartOfFrame = 0;
|
||||
else if(StructureField == 2) PartOfFrame = 1;
|
||||
else if(StructureField == 1) PartOfFrame = 2;
|
||||
else if(StructureField == 0) PartOfFrame = 3;
|
||||
else PartOfFrame = 0; /* Normally we should never go here */
|
||||
|
||||
/* Fill the SACCH structure */
|
||||
state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood;
|
||||
state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField;
|
||||
state->NxdnSacchRawPart[PartOfFrame].RAN = RAN;
|
||||
memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */
|
||||
|
||||
fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
|
||||
if(CrcIsGood) fprintf(stderr, " (OK) - ");
|
||||
else fprintf(stderr, "(CRC ERR) - ");
|
||||
|
||||
|
||||
/* This frame is an idle frame */
|
||||
fprintf(stderr, "Idle");
|
||||
|
||||
|
||||
/* Decode the SACCH only when all 4 voice frame
|
||||
* SACCH spare parts have been received */
|
||||
if(PartOfFrame == 3)
|
||||
{
|
||||
/* Decode the entire SACCH content */
|
||||
NXDN_SACCH_Full_decode(opts, state);
|
||||
}
|
||||
|
||||
for (i = 0; i < 144; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, "%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* Reset the SACCH CRCs when all 4 voice frame
|
||||
* SACCH spare parts have been received */
|
||||
if(PartOfFrame == 3)
|
||||
{
|
||||
/* Reset all CRCs of the SACCH */
|
||||
for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0;
|
||||
}
|
||||
} /* End ProcessNXDNIdleData() */
|
||||
|
||||
void ProcessNXDNFacch1Data (dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
int i, j, dibit = 0;
|
||||
unsigned char sacch_raw[72] = {0};
|
||||
unsigned char sacch_decoded[32] = {0}; /* 26 bits + 6 bits CRC */
|
||||
unsigned char facch1_raw[144] = {0};
|
||||
unsigned char facch1_decoded[96] = {0}; /* 80 bits + 12 bits CRC + 4 bits "Tail" (set to "0") */
|
||||
unsigned char *pr;
|
||||
uint8_t CrcIsGood = 0;
|
||||
uint8_t StructureField = 0;
|
||||
uint8_t RAN = 0;
|
||||
uint8_t PartOfFrame = 0;
|
||||
uint8_t Facch1CrcIsGood = 0;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf(stderr, "DATA - ");
|
||||
}
|
||||
|
||||
/* Start pseudo-random NXDN sequence after
|
||||
* LITCH = 16 bit = 8 dibit
|
||||
* ==> Index 8 */
|
||||
pr = (unsigned char *)(&nxdnpr[8]);
|
||||
for (i = 0; i < 30; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
|
||||
/* Store and de-interleave directly SACCH bits */
|
||||
sacch_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1
|
||||
sacch_raw[(2*i)+1] = (1 & dibit); // bit 0
|
||||
pr++;
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, "%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, " ");
|
||||
#endif
|
||||
|
||||
|
||||
/* Decode the SACCH fields */
|
||||
CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded);
|
||||
StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */
|
||||
RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */
|
||||
|
||||
/* Compute the Part of Frame according to the structure field */
|
||||
if (StructureField == 3) PartOfFrame = 0;
|
||||
else if(StructureField == 2) PartOfFrame = 1;
|
||||
else if(StructureField == 1) PartOfFrame = 2;
|
||||
else if(StructureField == 0) PartOfFrame = 3;
|
||||
else PartOfFrame = 0; /* Normally we should never go here */
|
||||
|
||||
/* Fill the SACCH structure */
|
||||
state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood;
|
||||
state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField;
|
||||
state->NxdnSacchRawPart[PartOfFrame].RAN = RAN;
|
||||
memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */
|
||||
|
||||
fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
|
||||
if(CrcIsGood) fprintf(stderr, " (OK) - ");
|
||||
else fprintf(stderr, "(CRC ERR) - ");
|
||||
|
||||
|
||||
/* This frame is an FACCH1 frame */
|
||||
fprintf(stderr, "FACCH1 - ");
|
||||
|
||||
|
||||
/* Decode the SACCH only when all 4 voice frame
|
||||
* SACCH spare parts have been received */
|
||||
if(PartOfFrame == 3)
|
||||
{
|
||||
/* Decode the entire SACCH content */
|
||||
//NXDN_SACCH_Full_decode(opts, state);
|
||||
}
|
||||
|
||||
/* Start pseudo-random NXDN sequence after
|
||||
* LITCH = 16 bit = 8 dibit +
|
||||
* SACCH = 60 bit = 30 dibit
|
||||
* = 76 bit = 38 dibit
|
||||
* ==> Index 38 */
|
||||
pr = (unsigned char *)(&nxdnpr[38]);
|
||||
|
||||
/* The frame contains 2 * 144 bits = 2 * 72 dibit */
|
||||
for(j = 0; j < 2; j++)
|
||||
{
|
||||
for (i = 0; i < 72; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
|
||||
/* Store and FACCH1 bits */
|
||||
facch1_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1
|
||||
facch1_raw[(2*i)+1] = (1 & dibit); // bit 0
|
||||
pr++;
|
||||
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, "%c", dibit + 48);
|
||||
#endif
|
||||
} /* End for (i = 0; i < 72; i++) */
|
||||
|
||||
/* Extract the FACCH1 content */
|
||||
Facch1CrcIsGood = NXDN_FACCH1_decode(facch1_raw, facch1_decoded);
|
||||
|
||||
state->NxdnFacch1RawPart[j].CrcIsGood = Facch1CrcIsGood;
|
||||
memcpy(state->NxdnFacch1RawPart[j].Data, facch1_decoded, 80);
|
||||
|
||||
if(Facch1CrcIsGood) fprintf(stderr, "FACCH1 CRC %d is good - ", j + 1);
|
||||
else fprintf(stderr, "FACCH1 CRC %d is bad - ", j + 1);
|
||||
} /* End for(j = 0; j < 2; j++) */
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* Reset the SACCH CRCs when all 4 voice frame
|
||||
* SACCH spare parts have been received */
|
||||
if(PartOfFrame == 3)
|
||||
{
|
||||
/* Reset all CRCs of the SACCH */
|
||||
for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0;
|
||||
}
|
||||
} /* End ProcessNXDNFacch1Data() */
|
||||
|
||||
void ProcessNXDNUdchData (dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
int i, dibit = 0;
|
||||
unsigned char facch2_raw[348] = {0};
|
||||
unsigned char facch2_decoded[203] = {0}; /* 184 bits + 15 bits CRC + 4 bits "Tail" (set to "0") */
|
||||
unsigned char *pr;
|
||||
uint8_t Facch2CrcIsGood = 0;
|
||||
uint8_t StructureField = 0;
|
||||
uint8_t RAN = 0;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf(stderr, "DATA - ");
|
||||
}
|
||||
|
||||
/* Start pseudo-random NXDN sequence after
|
||||
* LITCH = 16 bit = 8 dibit
|
||||
* ==> Index 8 */
|
||||
pr = (unsigned char *)(&nxdnpr[8]);
|
||||
for (i = 0; i < 174; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
|
||||
/* Store and de-interleave directly SACCH bits */
|
||||
facch2_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1
|
||||
facch2_raw[(2*i)+1] = (1 & dibit); // bit 0
|
||||
pr++;
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, "%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
#ifdef NXDN_DUMP
|
||||
fprintf(stderr, " ");
|
||||
#endif
|
||||
|
||||
/* Extract the UDCH/FACCH2 content */
|
||||
Facch2CrcIsGood = NXDN_UDCH_decode(facch2_raw, facch2_decoded);
|
||||
|
||||
state->NxdnFacch2RawPart.CrcIsGood = Facch2CrcIsGood;
|
||||
memcpy(state->NxdnFacch2RawPart.Data, facch2_decoded, 184);
|
||||
|
||||
StructureField = (facch2_decoded[0]<<1 | facch2_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the FACCH2) */
|
||||
RAN = (facch2_decoded[2]<<5 | facch2_decoded[3]<<4 | facch2_decoded[4]<<3 | facch2_decoded[5]<<2 | facch2_decoded[6]<<1 | facch2_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the FACCH2) */
|
||||
|
||||
fprintf(stderr, "RAN=%02d ", RAN);
|
||||
if(Facch2CrcIsGood) fprintf(stderr, " (OK) - ");
|
||||
else fprintf(stderr, "(CRC ERR) - ");
|
||||
|
||||
/* This frame is an FACCH2 frame */
|
||||
fprintf(stderr, "FACCH2 - ");
|
||||
|
||||
if(Facch2CrcIsGood) fprintf(stderr, "UDCH/FACCH2 CRC is good - ");
|
||||
else fprintf(stderr, "UDCH/FACCH2 CRC is bad - ");
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
} /* End ProcessNXDNUdchData() */
|
||||
|
||||
void ProcessNXDNFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
/* Switch to the correct type of frame */
|
||||
switch(state->NxdnLich.RFChannelType)
|
||||
{
|
||||
/* RCCH */
|
||||
case 0:
|
||||
{
|
||||
ProcessNxdnRCCHFrame(opts, state, Inverted);
|
||||
break;
|
||||
} /* End case 0 */
|
||||
|
||||
/* RTCH */
|
||||
case 1:
|
||||
{
|
||||
ProcessNxdnRTCHFrame(opts, state, Inverted);
|
||||
break;
|
||||
} /* End case 1 */
|
||||
|
||||
/* RDCH */
|
||||
case 2:
|
||||
{
|
||||
ProcessNxdnRDCHFrame(opts, state, Inverted);
|
||||
break;
|
||||
} /* End case 2 */
|
||||
|
||||
/* RTCH_C (Composite Control Channel) */
|
||||
case 3:
|
||||
{
|
||||
ProcessNxdnRTCH_C_Frame(opts, state, Inverted);
|
||||
break;
|
||||
} /* End case 3 */
|
||||
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "- Unknown NXDN Frame type\n");
|
||||
|
||||
/* Unknown frame type, simply skip the entire frame
|
||||
* 384 bits - 20 bits Frame Sync Word - 16 bits LICH = 348 bits = 174 dibit
|
||||
* Preserve 24 bits (12 dibit) => 174 - 12 = 162 dibit */
|
||||
skipDibit(opts, state, ((384 - 20 - 16) / 2) - 12);
|
||||
break;
|
||||
} /* End default */
|
||||
} /* End switch(state->NxdnLich.RFChannelType) */
|
||||
} /* End NxdnDecodeFrame() */
|
||||
|
||||
void ProcessNxdnRCCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
uint8_t SkipEntireFrameFlag = 0;
|
||||
|
||||
/* Remove compiler warning */
|
||||
// UNUSED_VARIABLE(Inverted);
|
||||
|
||||
sprintf(state->fsubtype, " RCCH ");
|
||||
|
||||
switch(state->NxdnLich.CompleteLich)
|
||||
{
|
||||
case 0b0011000:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - CCCH Transmission using Short CAC\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
case 0b0001000:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - UPCH or CCCH Transmission using Long CAC\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
case 0b0000001:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - CAC Transmission\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
case 0b0000011:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - CAC Transmission which has not to be received\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
case 0b0000101:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - CAC Transmission which can be received arbitrary\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
case 0b0011001:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - IDAS\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "- RCCH - Unknown RCCH Frame\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
} /* End default */
|
||||
} /* switch(state->NxdnLich.CompleteLich) */
|
||||
|
||||
if(SkipEntireFrameFlag)
|
||||
{
|
||||
/* Unknown frame type or frame not implemented yet, simply skip the entire frame
|
||||
* 384 bits - 20 bits Frame Sync Word - 16 bits LICH = 348 bits = 174 dibit
|
||||
* Preserve 24 bits (12 dibit) => 174 - 12 = 162 dibit */
|
||||
skipDibit(opts, state, ((384 - 20 - 16) / 2) - 12);
|
||||
}
|
||||
|
||||
} /* End ProcessNxdnRCCHFrame() */
|
||||
|
||||
void ProcessNxdnRDCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
uint8_t SkipEntireFrameFlag = 0;
|
||||
|
||||
/* Remove compiler warning */
|
||||
// UNUSED_VARIABLE(Inverted);
|
||||
|
||||
switch(state->NxdnLich.CompleteLich)
|
||||
{
|
||||
/* Voice frame */
|
||||
case 0b1010110: /* Voice call transmission : Superframe SACCH, VCH Only */
|
||||
case 0b1010100: /* Voice call transmission : Superframe SACCH, first half VCH & last half FACCH1 */
|
||||
case 0b1010010: /* Voice call transmission : Superframe SACCH, first half FACCH1 & last half VCH */
|
||||
case 0b1010111: /* Voice call transmission : Superframe SACCH, VCH Only */
|
||||
case 0b1010101: /* Voice call transmission : Superframe SACCH, first half VCH & last half FACCH1 */
|
||||
case 0b1010011: /* Voice call transmission : Superframe SACCH, first half FACCH1 & last half VCH */
|
||||
{
|
||||
fprintf(stderr, "- RDCH - ");
|
||||
processNXDNVoice(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1010000: /* Voice call transmission : Superframe SACCH, two FACCH1s */
|
||||
case 0b1010001: /* Voice call transmission : Superframe SACCH, two FACCH1s */
|
||||
{
|
||||
fprintf(stderr, "- RDCH - ");
|
||||
processNXDNData(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1011000: /* Voice call transmission : Superframe SACCH, Idle State */
|
||||
case 0b1011001: /* Voice call transmission : Superframe SACCH, Idle State */
|
||||
{
|
||||
fprintf(stderr, "- RDCH - ");
|
||||
ProcessNXDNIdleData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1000000: /* Voice call transmission : Non-superframe SACCH, two FACCH1s */
|
||||
case 0b1000001: /* Voice call transmission : Non-superframe SACCH, two FACCH1s */
|
||||
{
|
||||
//fprintf(stderr, "- RDCH - Non-superframe SACCH with two FACCH1s\n");
|
||||
fprintf(stderr, "- RDCH - ");
|
||||
ProcessNXDNFacch1Data(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1001110: /* UDCH Transmission */
|
||||
case 0b1001111: /* UDCH Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RDCH - UDCH Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1001000: /* FACCH2 Transmission */
|
||||
case 0b1001001: /* FACCH2 Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RDCH - FACCH2 Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "- RDCH - Unknown RDCH Frame\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
} /* End default */
|
||||
} /* End switch(state->NxdnLich.CompleteLich) */
|
||||
|
||||
if(SkipEntireFrameFlag)
|
||||
{
|
||||
/* Unknown frame type or frame not implemented yet, simply skip the entire frame
|
||||
* 384 bits - 20 bits Frame Sync Word - 16 bits LICH = 348 bits = 174 dibit
|
||||
* Preserve 8 bits (4 dibit) => 174 - 4 = 170 dibit */
|
||||
skipDibit(opts, state, ((384 - 20 - 16) / 2) - 4);
|
||||
}
|
||||
} /* End ProcessNxdnRDCHFrame() */
|
||||
|
||||
void ProcessNxdnRTCH_C_Frame(dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
uint8_t SkipEntireFrameFlag = 0;
|
||||
|
||||
/* Remove compiler warning */
|
||||
// UNUSED_VARIABLE(Inverted);
|
||||
|
||||
switch(state->NxdnLich.CompleteLich)
|
||||
{
|
||||
/* Voice frame */
|
||||
case 0b1110111: /* Voice call transmission : Superframe SACCH, VCH Only */
|
||||
case 0b1110101: /* Voice call transmission : Superframe SACCH, first half VCH & last half FACCH1 */
|
||||
case 0b1110011: /* Voice call transmission : Superframe SACCH, first half FACCH1 & last half VCH */
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - ");
|
||||
processNXDNVoice(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1110001: /* Voice call transmission : Superframe SACCH, two FACCH1s */
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - ");
|
||||
processNXDNData(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1111001: /* Voice call transmission : Superframe SACCH, Idle State */
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - ");
|
||||
ProcessNXDNIdleData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1100001: /* Voice call transmission : Non-superframe SACCH, two FACCH1s */
|
||||
{
|
||||
//fprintf(stderr, "- RTCH_C - Non-superframe SACCH with two FACCH1s\n");
|
||||
fprintf(stderr, "- RTCH_C - ");
|
||||
ProcessNXDNFacch1Data(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1101111: /* UDCH Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - UDCH Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b1101001: /* FACCH2 Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - FACCH2 Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "- RTCH_C - Unknown RTCH_C Frame\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
} /* End default */
|
||||
} /* End switch(state->NxdnLich.CompleteLich) */
|
||||
|
||||
if(SkipEntireFrameFlag)
|
||||
{
|
||||
/* Unknown frame type or frame not implemented yet, simply skip the entire frame
|
||||
* 384 bits - 20 bits Frame Sync Word - 16 bits LICH = 348 bits = 174 dibit
|
||||
* Preserve 8 bits (4 dibit) => 174 - 4 = 170 dibit */
|
||||
skipDibit(opts, state, ((384 - 20 - 16) / 2) - 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @brief : This function decodes an NXDN RTCH frame
|
||||
*
|
||||
* @param opts : Options
|
||||
*
|
||||
* @param state : State
|
||||
*
|
||||
* @param Inverted : 1 = Inverted frame ; 0 = Normal frame
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void ProcessNxdnRTCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted)
|
||||
{
|
||||
uint8_t SkipEntireFrameFlag = 0;
|
||||
|
||||
/* Remove compiler warning */
|
||||
// UNUSED_VARIABLE(Inverted);
|
||||
|
||||
switch(state->NxdnLich.CompleteLich)
|
||||
{
|
||||
/* Voice frame */
|
||||
case 0b0110110: /* Voice call transmission : Superframe SACCH, VCH Only */
|
||||
case 0b0110100: /* Voice call transmission : Superframe SACCH, first half VCH & last half FACCH1 */
|
||||
case 0b0110010: /* Voice call transmission : Superframe SACCH, first half FACCH1 & last half VCH */
|
||||
case 0b0110111: /* Voice call transmission : Superframe SACCH, VCH Only */
|
||||
case 0b0110101: /* Voice call transmission : Superframe SACCH, first half VCH & last half FACCH1 */
|
||||
case 0b0110011: /* Voice call transmission : Superframe SACCH, first half FACCH1 & last half VCH */
|
||||
{
|
||||
fprintf(stderr, "- RTCH - ");
|
||||
processNXDNVoice(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b0110000: /* Voice call transmission : Superframe SACCH, two FACCH1s */
|
||||
case 0b0110001: /* Voice call transmission : Superframe SACCH, two FACCH1s */
|
||||
{
|
||||
fprintf(stderr, "- RTCH - ");
|
||||
processNXDNData(opts, state);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b0111000: /* Voice call transmission : Superframe SACCH, Idle State */
|
||||
case 0b0111001: /* Voice call transmission : Superframe SACCH, Idle State */
|
||||
{
|
||||
fprintf(stderr, "- RTCH - ");
|
||||
ProcessNXDNIdleData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b0100000: /* Voice call transmission : Non-superframe SACCH, two FACCH1s */
|
||||
case 0b0100001: /* Voice call transmission : Non-superframe SACCH, two FACCH1s */
|
||||
{
|
||||
//fprintf(stderr, "- RTCH - Non-superframe SACCH with two FACCH1s\n");
|
||||
fprintf(stderr, "- RDCH - ");
|
||||
ProcessNXDNFacch1Data(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b0101110: /* UDCH Transmission */
|
||||
case 0b0101111: /* UDCH Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RTCH - UDCH Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0b0101000: /* FACCH2 Transmission */
|
||||
case 0b0101001: /* FACCH2 Transmission */
|
||||
{
|
||||
fprintf(stderr, "- RTCH - FACCH2 Transmission - ");
|
||||
ProcessNXDNUdchData(opts, state, Inverted);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "- RTCH - Unknown RTCH Frame\n");
|
||||
SkipEntireFrameFlag = 1;
|
||||
break;
|
||||
} /* End default */
|
||||
} /* End switch(state->NxdnLich.CompleteLich) */
|
||||
|
||||
if(SkipEntireFrameFlag)
|
||||
{
|
||||
/* Unknown frame type or frame not implemented yet, simply skip the entire frame
|
||||
* 384 bits - 20 bits Frame Sync Word - 16 bits LICH = 348 bits = 174 dibit
|
||||
* Preserve 8 bits (4 dibit) => 174 - 4 = 170 dibit */
|
||||
skipDibit(opts, state, ((384 - 20 - 16) / 2) - 4);
|
||||
}
|
||||
} /* End ProcessNxdnRTCHFrame() */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "dsd.h"
|
||||
#include "nxdn_const.h"
|
||||
|
||||
//don't know why this doesn't work right in LEH, need to figure that out for him
|
||||
//works just fien when ripped from his and into mine
|
||||
//must be some random thing, I'll look at his when I have a chance
|
||||
void processNXDNVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int i, j, dibit;
|
||||
@@ -143,11 +140,12 @@ void processNXDNVoice (dsd_opts * opts, dsd_state * state)
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
if (opts->payload == 1 && opts->dmr_stereo == 1)
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
//fprintf(stderr, "\n");
|
||||
}
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
state->p25vc++; //increment counter by one here?
|
||||
|
||||
} /* End for (j = 0; j < 4; j++) */
|
||||
|
||||
@@ -162,5 +160,6 @@ void processNXDNVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
/* Reset all CRCs of the SACCH */
|
||||
for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0;
|
||||
|
||||
}
|
||||
} /* End processNXDNVoice() */
|
||||
|
||||
30
src/p25_p2.c
Normal file
30
src/p25_p2.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*-------------------------------------------------------------------------------
|
||||
* p25_p2.c
|
||||
* Phase 2 TDMA Voice handling
|
||||
*
|
||||
* LWVMOBILE
|
||||
* 2022-08 DSD-FME Florida Man Edition
|
||||
*-----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "dsd.h"
|
||||
|
||||
void processP2(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
//Do Something
|
||||
fprintf (stderr, " Future Development\n"); //obligatory
|
||||
}
|
||||
@@ -467,12 +467,24 @@ processHDU(dsd_opts* opts, dsd_state* state)
|
||||
mihex1 = (unsigned long long int)ConvertBitIntoBytes(&mi[0], 32);
|
||||
mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32);
|
||||
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
|
||||
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
|
||||
state->payload_miP = (mihex1 << 32) | (mihex2);
|
||||
}
|
||||
|
||||
if (1 == 1) //print on payload == 1
|
||||
//set vc counter to 0
|
||||
state->p25vc = 0;
|
||||
|
||||
if (state->payload_algid != 0x80) //print on payload == 1
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX MFID: 0x%02X \n", algidhex, kidhex, mihex1, mihex2, mihex3, state->payload_mfid);
|
||||
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX MFID: 0x%02X", algidhex, kidhex, mihex1, mihex2, mihex3, state->payload_mfid);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
if (state->payload_algid != 0x80) //print on payload == 1
|
||||
{
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, " ENC \n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,17 @@ process_IMBE (dsd_opts* opts, dsd_state* state, int* status_count)
|
||||
#ifdef TRACE_DSD
|
||||
state->debug_prefix = '\0';
|
||||
#endif
|
||||
//check for enc, then always run below step and mute at the point of playing audio so we can still dump the frames
|
||||
if (state->payload_algid != 0x80)
|
||||
{
|
||||
state->dmr_encL = 1;
|
||||
}
|
||||
if (state->payload_algid == 0x80)
|
||||
{
|
||||
state->dmr_encL = 0;
|
||||
}
|
||||
|
||||
if (state->p25kid == 0 || opts->unmute_encrypted_p25 == 1)
|
||||
if (1 == 1) //state->p25kid == 0 || opts->unmute_encrypted_p25 == 1
|
||||
{
|
||||
{
|
||||
// Check for a non-standard c0 transmitted
|
||||
|
||||
@@ -65,7 +65,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '1';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 2
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[11][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[10][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -78,7 +77,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '2';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 3
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 7][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 6][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -91,7 +89,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '3';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 4
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 3][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 2][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -104,7 +101,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '4';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 5
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[11][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[10][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -117,7 +113,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '5';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 6
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 7][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 6][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -130,7 +125,6 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
||||
state->debug_prefix_2 = '6';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 7
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 3][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 2][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
|
||||
@@ -49,6 +49,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
// so we start counter at 36-14-1 = 21
|
||||
status_count = 21;
|
||||
|
||||
state->p25vc = 9;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
//fprintf (stderr, "e:");
|
||||
@@ -65,7 +67,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '1';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 2
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[15][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[14][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -78,7 +79,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '2';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 3
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[11][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[10][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -91,7 +91,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '3';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 4
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 7][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 6][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -104,7 +103,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '4';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 5
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 3][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_data[ 2][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -117,7 +115,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '5';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 6
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 7][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 6][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -130,7 +127,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '6';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 7
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 3][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
read_and_correct_hex_word (opts, state, &(hex_parity[ 2][0]), &status_count, analog_signal_array, &analog_signal_index);
|
||||
@@ -143,7 +139,6 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
state->debug_prefix_2 = '7';
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
// Read data after IMBE 8: LSD (low speed data)
|
||||
{
|
||||
char lsd[8];
|
||||
@@ -185,6 +180,9 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
#endif
|
||||
process_IMBE (opts, state, &status_count);
|
||||
|
||||
//set vc counter to 0
|
||||
state->p25vc = 0;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
@@ -373,48 +371,23 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
mihex1 = (unsigned long long int)ConvertBitIntoBytes(&mi[0], 32);
|
||||
mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32);
|
||||
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
|
||||
//need to check this for accuracy, may be incorrect, MI may also be incorrect, I have 72, but LFSR shows 64
|
||||
state->payload_miP = (mihex1 << 40) | (mihex2 << 8) | mihex3;
|
||||
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
|
||||
state->payload_miP = (mihex1 << 32) | (mihex2);
|
||||
|
||||
}
|
||||
|
||||
if (1 == 1) //print on payload == 1
|
||||
if (state->payload_algid != 0x80) //print on payload == 1
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3);
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
//LFSRP(state);
|
||||
}
|
||||
//why am I doing this part below again?
|
||||
if (opts->payload == 0)
|
||||
{
|
||||
algidhex = strtol (algid, NULL, 2);
|
||||
kidhex = strtol (kid, NULL, 2);
|
||||
}
|
||||
}
|
||||
|
||||
//needs some work to make mi value fit in there since its a 72 bit value, need to check this over
|
||||
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
||||
int LFSRP(dsd_state * state)
|
||||
{
|
||||
uint64_t lfsr = 0;
|
||||
lfsr = state->payload_miP;
|
||||
uint8_t cnt = 0;
|
||||
|
||||
for(cnt=0;cnt<32;cnt++)
|
||||
if (state->payload_algid != 0x80) //print on payload == 1
|
||||
{
|
||||
// Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1
|
||||
uint64_t bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1;
|
||||
lfsr = (lfsr << 1) | (bit);
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, " ENC \n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
|
||||
fprintf(stderr, " Next MI: 0x%016llX \n", lfsr);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
state->payload_miP = lfsr;
|
||||
|
||||
}
|
||||
|
||||
@@ -954,8 +954,10 @@ static void *socket_thread_fn(void *arg) {
|
||||
new_freq = chars_to_int(buffer);
|
||||
dongle.freq = new_freq; //
|
||||
//opts->rtlsdr_center_freq = new_freq; //or dongle.freq, this should update the freq displayed in ncurses terminal hopefully and not do anything naughty
|
||||
|
||||
optimal_settings(new_freq, demod.rate_in);
|
||||
rtlsdr_set_center_freq(dongle.dev, dongle.freq);
|
||||
//verbose_set_frequency (dongle.dev, new_freq);
|
||||
//fprintf (stderr, "Tuning to: %d [Hz] (central freq: %d [Hz])\n", new_freq, new_freq + freq_offset);
|
||||
fprintf (stderr, "Tuning to: %d [Hz] \n", new_freq);
|
||||
}
|
||||
@@ -1042,8 +1044,8 @@ static void *socket_thread_fn(void *arg) {
|
||||
|
||||
void rtlsdr_sighandler()
|
||||
{
|
||||
fprintf (stderr, "Signal caught, exiting!\n");
|
||||
fprintf (stderr, "Press CTRL + C again to close. Thanks. \n"); //Kindly remind user to double tap CTRL + C
|
||||
//fprintf (stderr, "Signal caught, exiting!\n");
|
||||
//fprintf (stderr, "Press CTRL + C again to close. Thanks. \n"); //Kindly remind user to double tap CTRL + C
|
||||
|
||||
rtlsdr_cancel_async(dongle.dev);
|
||||
//cleanup_rtlsdr_stream(); //thank the wraith for this one...if it works...didn't work
|
||||
@@ -1070,6 +1072,7 @@ void open_rtlsdr_stream(dsd_opts *opts)
|
||||
|
||||
if (opts->rtlsdr_ppm_error > 0 || opts->rtlsdr_ppm_error < 0) { //this way will adjust PPM based on negative values as well
|
||||
dongle.ppm_error = opts->rtlsdr_ppm_error;
|
||||
fprintf (stderr, "Setting RTL PPM Error Set to %d\n", opts->rtlsdr_ppm_error);
|
||||
}
|
||||
|
||||
if (opts->audio_in_type == 3) {
|
||||
@@ -1152,6 +1155,8 @@ void cleanup_rtlsdr_stream()
|
||||
safe_cond_signal(&output.ready, &output.ready_m);
|
||||
safe_cond_signal(&controller.hop, &controller.hop_m);
|
||||
pthread_join(controller.thread, NULL);
|
||||
//add socket thread
|
||||
//pthread_join(socket_freq, NULL);
|
||||
|
||||
//dongle_cleanup(&dongle);
|
||||
demod_cleanup(&demod);
|
||||
@@ -1162,16 +1167,29 @@ void cleanup_rtlsdr_stream()
|
||||
|
||||
}
|
||||
|
||||
void get_rtlsdr_sample(int16_t *sample)
|
||||
//void get_rtlsdr_sample(int16_t *sample)
|
||||
void get_rtlsdr_sample(int16_t *sample, dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
if (output.queue.empty())
|
||||
{
|
||||
if (opts->use_ncurses_terminal == 1)
|
||||
{
|
||||
//ncursesPrinter(opts, state);
|
||||
//printw ("\n\n\n HELP I'M LOCKED!\n");
|
||||
}
|
||||
safe_cond_wait(&output.ready, &output.ready_m);
|
||||
//goto END;
|
||||
}
|
||||
|
||||
pthread_rwlock_wrlock(&output.rw);
|
||||
//*sample = output.queue.front();
|
||||
|
||||
*sample = output.queue.front() * volume_multiplier; //try multiplying by numbers here for 'gain'
|
||||
output.queue.pop();
|
||||
pthread_rwlock_unlock(&output.rw);
|
||||
// END:
|
||||
// if (1 == 2)
|
||||
// {
|
||||
// fprintf (stderr, "This is a dumb thing to fix");
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user