Merge pull request #59 from lwvmobile/dmrstereo

DMR Stereo TDMA
This commit is contained in:
lwvmobile
2022-05-07 08:15:13 -04:00
committed by GitHub
35 changed files with 4190 additions and 1512 deletions

View File

@@ -1,64 +1,75 @@
# 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 a few tweaks from the [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve") branch as well. NXDN voice decoding is currently working a lot better, thanks to the latter, although I have yet to explore the expanded NXDN or DMR decoding he has laid out. That is a goal. I have also implemented a few more RTL options, including rtl device gain, PPM error, device index selection, squelch, VFO bandwidth, and a UDP remote that works like the old rtl_udp fork, although its currently limited to changing frequency and squelch. The goal is to integrate this project into [EDACS-FM](https://github.com/lwvmobile/edacs-fm "EDACS-FM") but I also want it to be its own standalone project.
# 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"), and [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"). 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, and hrh17 for the many hours of wav samples submitted by them.
## 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, any MBE file saving, WAV file saving, or MBE payloads 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.
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.
![DSD-FME](https://github.com/lwvmobile/dsd-fme/blob/pulseaudio/dsd-fme.png)
## Example Usage - NCurses Terminal and Log Console to log file
`./dsd -N 2> voice.log`
![DSD-FME](https://github.com/lwvmobile/dsd-fme/blob/pulseaudio/dsd-fme2.png)
in second terminal, same folder, run:
### Example Usage and Note!
`dsd` or `./dsd` 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 -h` for help and all command line switches to use.
`dsd` 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.
```
-fi NXDN48
-fn NXDN96
-fp ProVoice
-fm dPMR, also may need to use -xd if inverted dPMR.
-fr DMR, also may need to use -xr if inverted DMR, use -T for Stereo, and -F for passive sync
-f1 P25P1
-fx X2-TDMA
```
## Example Usage - New DMR Stereo, Ncurses Terminal, Pulse Input/Output, and Log Console to file
`dsd -fr -T -Z -N 2> voice.log`
and in a second terminal tab, same folder, run
`tail -n 40 -f voice.log`
## Example Usage - RTL
## Example Usage - RTL2832 Dongle Input
`dsd -fi -i rtl -c 154.9875M -P -2 -D 1 -G 36 -L 70 -U 6021 -Y 12`
```
-i rtl to use rtl_fm (default is -i pulse for pulse audio)
-o pulse to set output to pulse audio (is default anyways)
-o pulse to set output to pulse audio (excluded, is default anyways)
-c Set frequency
-P set PPM error
-P set PPM error (default = 0)
-D set device index number
-D set device index number (default = 0; first device detected)
-G set device gain (0-49) (default = 0 Auto Gain)
-L set rtl squelch to 25
-L set rtl squelch to 25 (default = 0; off)
-V set RTL sample 'volume' multiplier
-U set UDP port for rtl_fm remote control (default = 6020)
-U set UDP port for rtl_fm remote control
-Y 12 set rtl VFO bandwidth in kHz, (default = 48)(6, 8, 12, 16, 24, 48)
-Y 12 set rtl VFO bandwidth in kHz, (default = 12)(6, 8, 12, 16, 24, 48)
```
### Note
`dsd` and `./dsd` 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
## Example Pulse Audio Input and Pulse Audio Output, Autodetect Frame Type
`dsd` or `./dsd`
```
Yes, it really is this simple now
-fa Auto-detect frame type, is default
sans NXDN, dPMR, or Provoice, need to specify -fp, -fd, -fi, or -fn respectively
pulse audio is set as default input and output methods
```
## Example STDIN UDP from GQRX or SDR++, output to Pulse Audio, and save wav files
`socat stdio udp-listen:7355 | dsd -fi -i - -o pulse -w nxdn.wav`
## Example STDIN UDP from GQRX or SDR++, output to Pulse Audio, and append decoded audio to wav file
`socat stdio udp-listen:7355 | dsd -fi -i - -w nxdn.wav`
## Example Usage - Extra Information for Academic Study and Logging
Be sure to create a folder called MBE first and run
`dsd -d ./MBE/ -Z -pu 2>> voice.log`
in second terminal, same folder, run:
and in a second terminal tab, same folder, run
`tail -n 40 -f voice.log`
@@ -67,7 +78,7 @@ The Current list of objectives include:
1. ~~Random Tinkering~~ More Random Tinkering
2. ~~Implemented Pulse Audio~~ Remove PortAudio, improve Pulse Audio for stereo output and channel/slot separation.
2. ~~Implemented Pulse Audio~~ Remove PortAudio, ~~improved Pulse Audio for stereo output and channel/slot separation~~
3. ~~Improve NXDN and DMR support~~ Continue to improve ~~NXDN and DMR~~ all data and voice decoding.
@@ -77,9 +88,9 @@ The Current list of objectives include:
## How to clone, check out, and build this branch
### Ubuntu 20.04/LM20/Debian Bullseye or Newer:
### Ubuntu 22.04/20.04/LM20/Debian Bullseye or Newer:
Using the included install.sh should make for a simple and painless clone, build, and install on newer Debian or Ubuntu based system. Simply acquire or copy the script, and run it.
Using the included install.sh should make for a simple and painless clone, build, and install on newer Debian or Ubuntu based system. Simply acquire or copy the script, and run it. Update: Ubuntu 22.04 has been tested working with the installer script and use.
```
wget https://raw.githubusercontent.com/lwvmobile/dsd-fme/pulseaudio/install.sh
@@ -92,8 +103,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 Ubuntu 20.04 based distros. Check your package manager for equivalent packages if different. PortAudio is not currently used in this build, and is disabled in CMakeLists.txt, you can re-enable it if you wish, but it isn't recommended unless you have a very specific reason to do so. Some of these dependencies are not currently be used, but may be used in future builds.
First, install dependency packages. This guide will assume you are using Ubuntu 20.04 based distros. Check your package manager for equivalent packages if different. PortAudio is not used in this build!
```
sudo apt update

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 71 KiB

BIN
dsd-fme2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View File

@@ -17,6 +17,17 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
//pretty pretty colors
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
@@ -67,13 +78,11 @@
//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
/*
* global variables
*/
//
//
static volatile int exitflag;
//borrow from LEH
typedef struct
{
uint8_t RFChannelType;
@@ -148,8 +157,6 @@ typedef struct
} NxdnElementsContent_t;
//LEH DMR
enum
{
MODE_UNENCRYPTED,
@@ -230,8 +237,8 @@ typedef struct
FullLinkControlPDU_t FullLC;
} TimeSlotVoiceSuperFrame_t;
//end borrow from LEH
//LEH dPMR
//dPMR
/* Could only be 2 or 4 */
#define NB_OF_DPMR_VOICE_FRAME_TO_DECODE 2
@@ -293,11 +300,13 @@ typedef struct
int audio_out_type; // 0 for device, 1 for file, 2 for portaudio
int split;
int playoffset;
int playoffsetR;
char mbe_out_dir[1024];
char mbe_out_file[1024];
char mbe_out_path[1024];
FILE *mbe_out_f;
float audio_gain;
float audio_gainR;
int audio_out;
char wav_out_file[1024];
SNDFILE *wav_out_f;
@@ -337,27 +346,35 @@ typedef struct
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;
pa_simple *pulse_digi_dev_in;
pa_simple *pulse_digi_dev_out;
pa_simple *pulse_digi_dev_outR;
int use_ncurses_terminal;
int reset_state;
int payload;
char output_name[1024];
//LEH DMR Stuff
int EncryptionMode;
//LEH dPMR stuff
unsigned int dPMR_curr_frame_is_encrypted;
int dPMR_next_part_of_superframe;
int inverted_dpmr;
int frame_dpmr;
//
short int dmr_stereo;
//
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
} dsd_opts;
@@ -365,6 +382,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 repeat;
short *audio_out_buf;
short *audio_out_buf_p;
@@ -414,10 +433,14 @@ typedef struct
char tg[25][16];
int tgcount;
int lasttg;
int lasttgR;
int lastsrc;
int lastsrcR;
int nac;
int errs;
int errs2;
int errsR;
int errs2R;
int mbe_file_type;
int optind;
int numtdulc;
@@ -425,25 +448,38 @@ typedef struct
char slot0light[8];
//char slot1light[8];
float aout_gain;
float aout_gainR;
float aout_max_buf[200];
float aout_max_bufR[200];
float *aout_max_buf_p;
float *aout_max_buf_pR;
int aout_max_buf_idx;
int aout_max_buf_idxR;
int samplesPerSymbol;
int symbolCenter;
char algid[9];
char keyid[17];
int currentslot;
int hardslot;
mbe_parms *cur_mp;
mbe_parms *prev_mp;
mbe_parms *prev_mp_enhanced;
mbe_parms *cur_mp2;
mbe_parms *prev_mp2;
mbe_parms *prev_mp_enhanced2;
int p25kid;
int payload_algid;
int payload_algidR;
int payload_keyid;
int payload_keyidR;
int payload_mfid;
int payload_mfidR;
int payload_mi;
int payload_miR;
unsigned long long int K;
unsigned int debug_audio_errors;
unsigned int debug_audio_errorsR;
unsigned int debug_header_errors;
unsigned int debug_header_critical_errors;
@@ -459,17 +495,6 @@ typedef struct
//input sample buffer for monitoring Input
short input_sample_buffer; //HERE HERE
short pulse_raw_out_buffer; //HERE HERE
//float *input_sample_buffer; //HERE HERE
short dibit_to_hex_buf;
// state->sr_0 shift registers
short hexbuf;
unsigned long long sr_0; //64-bit shift registers for pushing decoded binary or dibit data
unsigned long long sr_1; //384
unsigned long long sr_2; //
unsigned long long sr_3; //
unsigned long long sr_4; //
unsigned long long sr_5; //
unsigned long long sr_6; //
unsigned int dmr_color_code;
unsigned int nxdn_last_ran;
@@ -478,10 +503,9 @@ typedef struct
unsigned int nxdn_cipher_type;
unsigned int nxdn_key;
char nxdn_call_type[1024];
char dmr_callsign[4][99]; //plenty of room in case of overflow;
char dmr_lrrp[6][9999];
char dmr_callsign[2][6][99]; //plenty of room in case of overflow;
char dmr_lrrp[2][6][9999];
//borrow from LEH
NxdnSacchRawPart_t NxdnSacchRawPart[4];
NxdnFacch1RawPart_t NxdnFacch1RawPart[2];
NxdnFacch2RawPart_t NxdnFacch2RawPart;
@@ -492,8 +516,7 @@ typedef struct
char ambe_ciphered[49];
char ambe_deciphered[49];
//end borrow
//LEH DMR struff
unsigned int color_code;
unsigned int color_code_ok;
unsigned int PI;
@@ -504,6 +527,9 @@ typedef struct
unsigned int dmr_fid;
unsigned int dmr_so;
unsigned int dmr_fidR;
unsigned int dmr_soR;
char slot1light[8];
char slot2light[8];
int directmode;
@@ -511,10 +537,11 @@ typedef struct
TimeSlotVoiceSuperFrame_t TS2SuperFrame;
char dmr_branding[25];
uint8_t dmr_12_rate_sf[36]; //going three frames deep
uint8_t dmr_34_rate_sf[54]; //going three frames deep
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
//LEH dPMR stuff
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
//These flags are used to known the DMR frame
@@ -539,6 +566,15 @@ typedef struct
unsigned char * dpmr_target_id;
int dpmr_color_code;
short int dmr_stereo; //need state variable for upsample function
short int dmr_ms_rc;
short int dmr_ms_mode;
unsigned int dmrburstL;
unsigned int dmrburstR;
//dstar header for ncurses
unsigned char dstarradioheader[41];
#ifdef TRACE_DSD
char debug_prefix;
char debug_prefix_2;
@@ -555,6 +591,10 @@ typedef struct
/*
* Frame sync patterns
*/
#define FUSION_SYNC "31111311313113131131" //HA!
#define INV_FUSION_SYNC "13333133131331313313" //HA!
#define INV_P25P1_SYNC "333331331133111131311111"
#define P25P1_SYNC "111113113311333313133333"
@@ -568,14 +608,6 @@ typedef struct
#define DSTAR_SYNC "313131313133131113313111"
#define INV_DSTAR_SYNC "131313131311313331131333"
//bogus nxdnn data syncs to troubleshoot
/*
#define NXDN_MS_DATA_SYNC "33333313133113131111333333333111"
#define INV_NXDN_MS_DATA_SYNC "11133331313113313133331113333331"
#define INV_NXDN_BS_DATA_SYNC "33331111313113313133331313333333"
#define NXDN_BS_DATA_SYNC "11113333131331131311113133333333"
//end bogus nxdn data syncs
*/
#define NXDN_MS_DATA_SYNC "313133113131111333"
#define INV_NXDN_MS_DATA_SYNC "131311331313333111"
#define INV_NXDN_BS_DATA_SYNC "131311331313333131"
@@ -589,64 +621,52 @@ typedef struct
#define DMR_BS_VOICE_SYNC "131111333113313313113313"
#define DMR_MS_DATA_SYNC "311131133313133331131113"
#define DMR_MS_VOICE_SYNC "133313311131311113313331"
//borrow extra syncs from LEH
//inversion testing on MS
//#define DMR_MS_DATA_SYNC "133313311131311113313331"
//#define DMR_MS_VOICE_SYNC "311131133313133331131113"
#define DMR_RC_DATA_SYNC "131331111133133133311313"
#define DMR_DIRECT_MODE_TS1_DATA_SYNC "331333313111313133311111"
#define DMR_DIRECT_MODE_TS1_VOICE_SYNC "113111131333131311133333"
#define DMR_DIRECT_MODE_TS2_DATA_SYNC "311311111333113333133311"
#define DMR_DIRECT_MODE_TS2_VOICE_SYNC "133133333111331111311133"
//end LEH
#define INV_PROVOICE_SYNC "31313111333133133311331133113311"
#define PROVOICE_SYNC "13131333111311311133113311331133"
#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311"
#define PROVOICE_EA_SYNC "31131311331331111133131311311133"
//LEH dPMR
/* dPMR Frame Sync 1 - 48 bits sequence
* HEX : 57 FF 5F 75 D5 77
* Binary : 0101 0111 1111 1111 0101 1111 0111 0101 1101 0101 0111 0111
* Dibit : 1 1 1 3 3 3 3 3 1 1 3 3 1 3 1 1 3 1 1 1 1 3 1 3 */
#define DPMR_FRAME_SYNC_1 "111333331133131131111313"
/* dPMR Frame Sync 2 - 24 bits sequence
* HEX : 5F F7 7D
* Binary : 0101 1111 1111 0111 0111 1101
* Dibit : 1 1 3 3 3 3 1 3 1 3 3 1 */
#define DPMR_FRAME_SYNC_2 "113333131331"
/* dPMR Frame Sync 3 - 24 bits sequence
* HEX : 7D DF F5
* Binary : 0111 1101 1101 1111 1111 0101
* Dibit : 1 3 3 1 3 1 3 3 3 3 1 1 */
#define DPMR_FRAME_SYNC_3 "133131333311"
/* dPMR Frame Sync 4 - 48 bits sequence
* HEX : FD 55 F5 DF 7F DD
* Binary : 1111 1101 0101 0101 1111 0101 1101 1111 0111 1111 1101 1101
* Dibit : 3 3 3 1 1 1 1 1 3 3 1 1 3 1 3 3 1 3 3 3 3 1 3 1 */
#define DPMR_FRAME_SYNC_4 "333111113311313313333131"
//#define DPMR_FRAME_SYNC_4 "111333331133131131111313"
/* dPMR Frame Sync 1 to 4 - Inverted */
#define INV_DPMR_FRAME_SYNC_1 "333111113311313313333131"
#define INV_DPMR_FRAME_SYNC_2 "331111313113"
#define INV_DPMR_FRAME_SYNC_3 "311313111133"
#define INV_DPMR_FRAME_SYNC_4 "111333331133131131111313"
//#define INV_DPMR_FRAME_SYNC_4 "333111113311313313333131"
//
/*
* function prototypes
*/
void processDMRdata (dsd_opts * opts, dsd_state * state);
void processDMRvoice (dsd_opts * opts, dsd_state * state);
void dmrBSBootstrap (dsd_opts * opts, dsd_state * state);
void dmrBS (dsd_opts * opts, dsd_state * state);
void dmrMS (dsd_opts * opts, dsd_state * state);
void dmrMSData (dsd_opts * opts, dsd_state * state);
void dmrMSBootstrap (dsd_opts * opts, dsd_state * state);
void processdPMRvoice (dsd_opts * opts, dsd_state * state);
void processAudio (dsd_opts * opts, dsd_state * state);
void playRawAudio (dsd_opts * opts, dsd_state * state); //added this one HERE HERE
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 writeSynthesizedVoice (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);
void openAudioInDevice (dsd_opts * opts);
@@ -695,10 +715,11 @@ void processProVoice (dsd_opts * opts, dsd_state * state);
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
short dmr_filter(short sample);
short nxdn_filter(short sample);
//borrow from LEH for testing 'improved NXDN detection'
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);
@@ -711,7 +732,7 @@ void ncursesOpen ();
void ncursesPrinter (dsd_opts * opts, dsd_state * state);
void ncursesClose ();
//endif ncurses
//borrow from LEH
/* NXDN frame decoding functions */
void ProcessNXDNFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted);
void ProcessNxdnRCCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted);
@@ -722,7 +743,7 @@ void ProcessNXDNIdleData (dsd_opts * opts, dsd_state * state, uint8_t Inverted);
void ProcessNXDNFacch1Data (dsd_opts * opts, dsd_state * state, uint8_t Inverted);
void ProcessNXDNUdchData (dsd_opts * opts, dsd_state * state, uint8_t Inverted);
//end borrow
//borrow from LEH
/* NXDN functions */
void CNXDNConvolution_start(void);
void CNXDNConvolution_decode(uint8_t s0, uint8_t s1);
@@ -751,7 +772,7 @@ 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);
//LEH dPMR
void dPMRVoiceFrameProcess(dsd_opts * opts, dsd_state * state);
void printdPMRAmbeVoiceSample(dsd_opts * opts, dsd_state * state);
void printdPMRRawVoiceFrame (dsd_opts * opts, dsd_state * state);
@@ -762,7 +783,7 @@ uint8_t CRC7BitdPMR(uint8_t * BufferIn, uint32_t BitLength);
uint8_t CRC8BitdPMR(uint8_t * BufferIn, uint32_t BitLength);
void ConvertAirInterfaceID(uint32_t AI_ID, uint8_t ID[8]);
int32_t GetdPmrColorCode(uint8_t ChannelCodeBit[24]);
//LEH DMR
void ProcessDMR (dsd_opts * opts, dsd_state * state);
void DMRDataFrameProcess(dsd_opts * opts, dsd_state * state);
void DMRVoiceFrameProcess(dsd_opts * opts, dsd_state * state);
@@ -797,6 +818,7 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98]
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 ProcessUnifiedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
void Hamming_7_4_init();
@@ -836,10 +858,8 @@ void QR_16_7_6_encode(unsigned char *origBits, unsigned char *encodedBits);
bool QR_16_7_6_decode(unsigned char *rxBits);
void InitAllFecFunction(void);
//end borrow from LEH
void resetState (dsd_state * state);
void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]);
#ifdef __cplusplus
extern "C" {
@@ -860,6 +880,8 @@ 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

View File

@@ -2,5 +2,5 @@
#ifndef _DSTAR_HEADER_H
#define _DSTAR_HEADER_H
void dstar_header_decode(int radioheaderbuffer[660]);
#endif /* _DSTAR_HEADER_H */
//void dstar_header_decode(int radioheaderbuffer[660]);
#endif /* _DSTAR_HEADER_H */

465
src/dmr_bs.c Normal file
View File

@@ -0,0 +1,465 @@
#include "dsd.h"
#include "dmr_const.h"
//A subroutine for processing each TDMA frame individually to allow for
//processing voice and/or data on both BS slots (channels) simultaneously
void dmrBS (dsd_opts * opts, dsd_state * state)
{
int i, j, k, l, dibit;
int *dibit_p;
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];
char syncdata[48];
char cachdata[13] = {0};
int mutecurrentslot;
int msMode;
char cc[4];
unsigned char EmbeddedSignalling[16];
int EmbeddedSignallingOk;
unsigned int internalcolorcode;
int internalslot;
char redundancyA[36];
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
{
time_t t = time(NULL);
char * curr;
char * stamp = asctime(localtime( & t));
curr = strtok(stamp, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
return curr;
}
//Init the superframe buffers
//memset(&state->TS1SuperFrame, 0, sizeof(TimeSlotVoiceSuperFrame_t));
//memset(&state->TS2SuperFrame, 0, sizeof(TimeSlotVoiceSuperFrame_t));
//Init the color code status
state->color_code_ok = 0;
vc1 = 2;
vc2 = 2;
short int loop = 1;
short int skipcount = 0;
//Run Loop while the getting is good
while (loop == 1) {
// CACH
internalslot = -1; //reset here so we know if this value is being set properly
for(i = 0; i < 12; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
state->dmr_stereo_payload[i] = dibit;
if(i == 2)
{
state->currentslot = (1 & (dibit >> 1));
internalslot = (1 & (dibit >> 1));
}
}
//Setup for first AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//First AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+12] = dibit;
redundancyA[i] = dibit;
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//check for repetitive data if caught in a 'no carrier' loop? Just picking random values.
//this will test for no carrier (input signal) and return us to no sync state if necessary
if (redundancyA[16] == redundancyB[16] && redundancyA[27] == redundancyB[27] &&
redundancyA[01] == redundancyB[01] && redundancyA[32] == redundancyB[32] &&
redundancyA[03] == redundancyB[03] && redundancyA[33] == redundancyB[33] &&
redundancyA[13] == redundancyB[13] && redundancyA[07] == redundancyB[07] )
{
goto END;
}
// end redundancy test, set B to A
for(i = 0; i < 36; i++)
{
redundancyB[i] = redundancyA[i];
}
//Setup for Second AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+48] = dibit;
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//short int l = 0; //do I still use this?
// signaling data or sync
for(i = 0; i < 24; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+66] = dibit;
syncdata[(2*i)] = (1 & (dibit >> 1)); // bit 1
syncdata[(2*i)+1] = (1 & dibit); // bit 0
sync[i] = (dibit | 1) + 48;
if (i < 4 || i > 19) //
{
EmbeddedSignalling[2*i] = (1 & (dibit >> 1)); // bit 1
EmbeddedSignalling[2*i+1] = (1 & dibit); // bit 0
}
//Used for ProcessVoiceBurstSync
if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E
{
/* Time slot 1 superframe buffer filling => SYNC data */
state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1
state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2+1] = (1 & dibit); // bit 0
}
if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E
{
/* Time slot 2 superframe buffer filling => SYNC data */
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;
EmbeddedSignallingOk = -1;
if(QR_16_7_6_decode(EmbeddedSignalling))
{
EmbeddedSignallingOk = 1;
}
internalcolorcode = 69; //set so we know if this value is being set properly
if(EmbeddedSignallingOk == 1)
{
state->color_code = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
internalcolorcode = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
state->color_code_ok = EmbeddedSignallingOk;
//Power Indicator, not the other PI (header)
state->PI = (unsigned int)EmbeddedSignalling[4];
state->PI_ok = EmbeddedSignallingOk;
//Link Control Start Stop Indicator
state->LCSS = (unsigned int)((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
state->LCSS_ok = EmbeddedSignallingOk;
}
else skipcount++;
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+90] = dibit;
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//Setup for Third AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Third AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+108] = dibit;
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//reset vc counters to 1 if new voice sync frame on each slot
if ( (strcmp (sync, DMR_BS_VOICE_SYNC) == 0) )
{
if (internalslot == 0)
{
vc1 = 1;
}
if (internalslot == 1)
{
vc2 = 1;
}
}
//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) )
{
fprintf (stderr,"%s ", getTime());
if (internalslot == 0)
{
sprintf(state->slot1light, "[slot1]");
sprintf(state->slot2light, " slot2 ");
//fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | Data ", state->color_code);
fprintf (stderr,"Sync: +DMR ");
//constantly reset the vc counter to 1 each data frame in anticipation of new voice frame
vc1 = 1;
}
if (internalslot == 1)
{
sprintf(state->slot2light, "[slot2]");
sprintf(state->slot1light, " slot1 ");
//fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | Data ", state->color_code);
fprintf (stderr,"Sync: +DMR ");
//constantly reset the vc counter to 1 each data frame in anticipation of new voice frame
vc2 = 1;
}
processDMRdata (opts, state);
skipcount++; //after 6 data frames, drop back to getFrameSync and process subsequent data with processDMRdata
goto SKIP;
}
if( (strcmp (sync, DMR_BS_DATA_SYNC) != 0) ) //only play voice no data sync // || (strcmp (sync, DMR_MS_DATA_SYNC) != 0)
{
if (EmbeddedSignallingOk == 0)
{
//goto END;
}
skipcount = 0; //reset skip count if processing voice frames
fprintf (stderr,"%s ", getTime());
if (internalslot == 0)
{
state->dmrburstL = 16; //use 16 for Voice?
fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc1);
}
if (internalslot == 1)
{
state->dmrburstR = 16; //use 16 for Voice?
fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc2);
}
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");
}
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
if (internalslot == 0)
{
vc1++;
}
if (internalslot == 1)
{
vc2++;
}
}
// recalibrate center/umid/lmid, not sure this helps or does anything particularly in this case
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;
//Escape conditions to break the loop
//7 seems optimal, allows for an extra frame each in case of late entry on dual voices
if ( (vc1 > 7 && vc2 > 7) )
{
goto END;
}
//14 probably allows a few more in case of a bit of jitter but eventually breaks loop (1 second?)
if ( (vc1 > 14 || vc2 > 14) )
{
goto END;
}
//using these conditions may cause excessive resyncs IF bad signal,
//but still better than getting stuck in a wonk wonk loop for too long.
//set for more aggressive or less aggressive resync during accumulated playback errs
if (opts->aggressive_framesync == 1)
{
//errors caused due to playing MBE files out of sync, break loop
if (state->errs > 2 || state->errsR > 2)
{
//goto END; //
}
//errors caused due to playing MBE files out of sync, break loop
if (state->errs2 > 4 || state->errs2R > 4)
{
goto END; //
}
}
//earlier skip conditions teleport us here to process further skip conditions before restarting while loop
SKIP:
if (skipcount > 2) //after 2 consecutive data frames, drop back to getFrameSync and process with processDMRdata
{
goto END;
}
//since we are in a while loop, run ncursesPrinter here.
if (opts->use_ncurses_terminal == 1)
{
ncursesPrinter(opts, state);
}
} // while loop
//Teleport here on END condition, set or reset variables and return to look for new frame sync
END:
state->dmr_stereo = 0;
state->errs2R = 0;
state->errs2 = 0;
}
//Only process 2nd half voice payload (3rd frame) and then jump to full BS decoding
void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
{
int i, j, k, l, dibit;
int *dibit_p;
char ambe_fr[4][24] = {0};
char ambe_fr2[4][24] = {0};
char ambe_fr3[4][24] = {0};
const int *w, *x, *y, *z;
char sync[25];
char syncdata[48];
char cachdata[13] = {0};
int mutecurrentslot;
int msMode;
char cc[4];
unsigned char EmbeddedSignalling[16];
unsigned int EmbeddedSignallingOk;
//add time to mirror printFrameSync
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
{
time_t t = time(NULL);
char * curr;
char * stamp = asctime(localtime( & t));
curr = strtok(stamp, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
return curr;
}
//skip the 18 dibits of the 2nd frame, since we can't play only half a frame
skipDibit (opts, state, 18);
//Setup for Third AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Third AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//fprintf (stderr,"\n%s ", getTime());
fprintf (stderr,"%s ", getTime());
fprintf (stderr,"Sync: +DMR | Frame Sync | DMRSTEREO | VC1 FS \n");
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
dmrBS (opts, state); //bootstrap into full TDMA frame for BS mode
}

View File

@@ -49,6 +49,12 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
bursttype[4] = 0;
dibit_p = state->dibit_buf_p - 90;
//using the estimate_symbol method for the dmr_payload_p buffer causes sync
//issues with P25, so only do it when frame_p25p1 == 0, or -fr option
if (opts->frame_p25p1 == 0) //opts->frame_p25p1 == 0
{
dibit_p = state->dmr_payload_p - 90;
}
// CACH
for (i = 0; i < 12; i++)
@@ -59,6 +65,11 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[i];
}
//fprintf(stderr, "%X", dibit);
cachdata[i] = dibit;
if (i == 2)
{
@@ -79,6 +90,15 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
//method to only see data from one slot or the other when data occupies both slots or gets cooked by sync
state->hardslot = 9; //0 to only listen to slot 0 voice, 1 for slot 1, 9 for both
if(state->hardslot != 9 && state->hardslot != state->currentslot)
//if(1==1)
{
fprintf (stderr, " Current Slot = %d", state->currentslot + 1);
fprintf (stderr, "\n"); //line break after breaking out of jail
//goto JUMP;
}
}
}
cachdata[12] = 0;
@@ -107,6 +127,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[i+12];
}
trellisdibits[i] = dibit;
info[2*i] = (1 & (dibit >> 1)); // bit 1
info[(2*i)+1] = (1 & dibit); // bit 0
@@ -119,6 +143,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[61]; //61, not i+61
}
cc[0] = (1 & (dibit >> 1)); // bit 1
cc[1] = (1 & dibit); // bit 0
SlotType[0] = (1 & (dibit >> 1)); // bit 1
@@ -130,6 +158,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[62];
}
cc[2] = (1 & (dibit >> 1)); // bit 1
cc[3] = (1 & dibit); // bit 0
SlotType[2] = (1 & (dibit >> 1)); // bit 1
@@ -147,6 +179,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1) //state
{
dibit = (int)state->dmr_stereo_payload[63]; //(int)
}
// burst = (unsigned int)((1 & (dibit >> 1)) << 3);
// burst |= (unsigned int)((1 & (dibit >> 0)) << 2);
// bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1
@@ -160,6 +196,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1) //state
{
dibit = (int)state->dmr_stereo_payload[64]; //(int)
}
// burst |= (unsigned int)((1 & (dibit >> 1)) << 1);
// burst |= (unsigned int)((1 & (dibit >> 0)) << 0);
// bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1
@@ -174,6 +214,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[65];
}
SlotType[8] = (1 & (dibit >> 1)); // bit 1
SlotType[9] = (1 & dibit); // bit 0
@@ -186,6 +230,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[i+66]; //double check these i+ values make sure we are on the right ones
}
syncdata[2*i] = (1 & (dibit >> 1)); // bit 1
syncdata[(2*i)+1] = (1 & dibit); // bit 0
sync[i] = (dibit | 1) + 48;
@@ -216,6 +264,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
sprintf(state->slot2light, "[slot2]");
}
}
else if(strcmp (sync, DMR_DIRECT_MODE_TS1_DATA_SYNC) == 0)
{
state->currentslot = 0;
@@ -236,11 +285,18 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
// Slot type - Second part - Parity bit
for (i = 0; i < 5; i++)
{
dibit = getDibit(opts, state);
if (state->dmr_stereo == 0) //only get dibits if not using dmr_stereo method
{
dibit = getDibit(opts, state);
}
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[i+90]; //double checked these i+ values make sure we are on the right ones
}
SlotType[(i*2) + 10] = (1 & (dibit >> 1)); // bit 1
SlotType[(i*2) + 11] = (1 & dibit); // bit 0
}
@@ -250,11 +306,23 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
else SlotTypeOk = 0;
/* Slot Type parity checked => Fill the color code */
state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]);
//state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]);
state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0);
state->color_code_ok = SlotTypeOk;
//fprintf(stderr, "| Color Code=%02d ", (int)state->color_code);
/* Reconstitute the burst type */
//consider assigning thsi only when slottypeok or similar check passes, eliminate bad burst types from decoding randomly
burst = (unsigned int)((SlotType[4] << 3) + (SlotType[5] << 2) + (SlotType[6] << 1) + SlotType[7]);
if (state->currentslot == 0)
{
state->dmrburstL = burst;
}
if (state->currentslot == 1)
{
state->dmrburstR = burst;
}
/* Reconstitute the burst type */
bursttype[0] = SlotType[4] + '0';
@@ -263,13 +331,55 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
bursttype[3] = SlotType[7] + '0';
bursttype[4] = '\0';
/* //delete this chunk later
if (state->dmr_stereo == 3) //may not need this any longer
{
burst = (state->dmr_stereo_payload[63] << 2) | (state->dmr_stereo_payload[64]);
//this whole split for getting burst and burst type is makes no sense
//why not just use burst
bursttype[0] = (((state->dmr_stereo_payload[63] >> 1) & 1) + '0');
bursttype[1] = (((state->dmr_stereo_payload[63] >> 0) & 1) + '0');
bursttype[2] = (((state->dmr_stereo_payload[64] >> 1) & 1) + '0');
bursttype[3] = (((state->dmr_stereo_payload[64] >> 0) & 1) + '0');
bursttype[4] = '\0';
//fprintf(stderr, "BURST1 = %04b ", burst);
}
//figure out why the sync is wrong when dumping the payload to processDMRdata for MS Data
//I think its a conversion issue with the payload(chat) from the dibit buffer (int *)
//actually, its the dibit buffer storing as 1 and 3 only (GFSK) when sync drops
//made a seperate dmr buffer, but still, when sync loss and regain, takes a few syncs to calibrate center/umid/lmid properly
//getting accurate MS data AND leading BS data may be impossible without saving the symbols, calibrating, then going back
//and running the buffer payload, but I honestly don't know right now, probably easier to start from stratch than fix this
if (state->dmr_ms_mode == 7)
{
burst = (unsigned int)((SlotType[4] << 3) | (SlotType[5] << 2) | (SlotType[6] << 1) | SlotType[7]);
bursttype[0] = SlotType[4] + '0';
bursttype[1] = SlotType[5] + '0';
bursttype[2] = SlotType[6] + '0';
bursttype[3] = SlotType[7] + '0';
bursttype[4] = '\0';
//fprintf(stderr, "BURST1 = %04b ", burst);
}
if (state->dmr_stereo == 3)
{
fprintf(stderr, "BURST2 = %b%b%b%b Slot Dump ", SlotType[4], SlotType[5], SlotType[6], SlotType[7] );
fprintf(stderr, " Slot Dump = ");
for (i = 0; i < 20; i++)
{
fprintf(stderr, "%b", SlotType[i]);
}
fprintf(stderr, "\n ");
}
*/
if (strcmp (bursttype, "0000") == 0)
{
sprintf(state->fsubtype, " PI Header ");
}
else if (strcmp (bursttype, "0001") == 0)
{
sprintf(state->fsubtype, " VOICE Header ");
sprintf(state->fsubtype, " VOICE LC Header ");
}
else if (strcmp (bursttype, "0010") == 0)
{
@@ -316,31 +426,55 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
//trellis
for (i = 0; i < 49; i++)
{
dibit = getDibit(opts, state);
if (state->dmr_stereo == 0) //only get dibits if not using dmr_stereo method
{
dibit = getDibit(opts, state);
}
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
if (state->dmr_stereo == 1)
{
dibit = (int)state->dmr_stereo_payload[i+95]; //double checked these i+ values make sure we are on the right ones
}
trellisdibits[i+49] = dibit;
info[(2*i) + 98] = (1 & (dibit >> 1)); // bit 1
info[(2*i) + 99] = (1 & dibit); // bit 0
}
// Skip cach (24 bit = 12 dibit) and next slot 1st half (98 + 10 bit = 49 + 5 dibit)
skipDibit (opts, state, 12 + 49 + 5);
if (state->dmr_stereo == 0)
{
skipDibit (opts, state, 12 + 49 + 5);
}
if (opts->errorbars == 1)
{
/* Print the color code */
fprintf(stderr, "| Color Code=%02d ", (int)state->color_code);
//if (burst == 0b1001 && state->color_code_ok) //only print on idle for data types, otherwise prints on voice frames.
if (SlotTypeOk == 1)
{
fprintf (stderr, "%s", KCYN);
fprintf(stderr, "| Color Code=%02d ", (int)state->color_code);
fprintf (stderr, "%s", KNRM);
//state->dmr_color_code = state->color_code;
}
else fprintf(stderr, "| ");
//if(state->color_code_ok) fprintf(stderr, "(OK) |");
if(state->color_code_ok) fprintf(stderr, "(CRC OK ) |"); //add line break
else fprintf(stderr, "(CRC ERR) |"); //add line break
if(state->color_code_ok) fprintf(stderr, "| (CRC OK ) |"); //add line break
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, "| (CRC ERR) |");
fprintf (stderr, "%s", KNRM);
}
//fprintf (stderr, "\n"); //print line break
if (strcmp (state->fsubtype, " ") == 0)
{
fprintf(stderr, " Unknown burst type: %s", bursttype);
//fprintf(stderr, " Unknown burst type: %s", bursttype);
fprintf(stderr, " Unknown");
}
else
{
@@ -368,6 +502,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
/* Burst = TLC */
case 0b0010:
{
//Not sure if I really care about this in the context of what it shows
ProcessDmrTerminaisonLC(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
break;
}
@@ -375,6 +510,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
/* Burst = CSBK */
case 0b0011:
{
//going to disable until I can find more useful info to present
ProcessCSBK(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
break;
}
@@ -386,7 +522,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
break;
}
/* Burst = MBC */
/* Burst = MBC Continuation*/
case 0b0101:
{
//ProcessMBCData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
@@ -410,14 +546,15 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
/* Burst = RATE 3/4 DATA */
case 0b1000:
{
//disabled until a viable viterbi/trellis decoding solution is worked out
//Process34Data(opts, state, trellisdibits, (uint8_t *)syncdata, (uint8_t *)SlotType);
//need to keep working on improving the trellis decode, but is partially viable now
Process34Data(opts, state, trellisdibits, (uint8_t *)syncdata, (uint8_t *)SlotType);
break;
}
/* Burst = Slot idle */
case 0b1001:
{
if(state->color_code_ok) state->dmr_color_code = state->color_code; //try setting this on idle if crc ok
break;
}
@@ -428,10 +565,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
break;
}
/* Burst = WTF 1101 Type DATA */
/* Burst = Unified Single Block DATA */
case 0b1101:
{
//ProcessWTFData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
//ProcessUnifiedData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
break;
}
@@ -448,5 +585,5 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
{
fprintf(stderr, "\n");
}
//JUMP:
} /* End processDMRdata() */

672
src/dmr_ms.c Normal file
View File

@@ -0,0 +1,672 @@
#include "dsd.h"
#include "dmr_const.h"
//A subroutine for processing MS voice
void dmrMS (dsd_opts * opts, dsd_state * state)
{
//fprintf (stderr, "\n Quick DMR Voice Testing\n");
int i, j, k, l, dibit;
int *dibit_p;
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];
char syncdata[48];
//standalone inbound rc sync exists on dibits 48-96?
//or 44-92? of each potential payload, middle 10 ms or 30 ms frame
char rcsync[25];
char rcsyncdata[96]; //96 bit RC sync data
char cachdata[13] = {0};
int mutecurrentslot;
int msMode;
char cc[4];
unsigned char EmbeddedSignalling[16];
int EmbeddedSignallingOk;
unsigned int internalcolorcode;
int internalslot;
int activeslot;
char redundancyA[36];
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
{
time_t t = time(NULL);
char * curr;
char * stamp = asctime(localtime( & t));
curr = strtok(stamp, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
return curr;
}
//Init the color code status
state->color_code_ok = 0;
vc1 = 2;
vc2 = 2;
short int loop = 1;
short int skipcount = 0;
//Hardset variables for MS
state->currentslot = 0;
internalslot = 0;
activeslot = 0;
//Run Loop while the getting is good
while (loop == 1) {
state->dmrburstL = 16; //Use 16 for Voice?
// No CACH in MS Mode?
for(i = 0; i < 12; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
state->dmr_stereo_payload[i] = dibit;
if(i == 2)
{
//state->currentslot = (1 & (dibit >> 1));
//internalslot = (1 & (dibit >> 1));
}
}
//Setup for first AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//First AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+12] = dibit;
redundancyA[i] = dibit;
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//check for repetitive data if caught in a 'no carrier' loop? Just picking random values.
//this will test for no carrier (input signal) and return us to no sync state if necessary
if (redundancyA[16] == redundancyB[16] && redundancyA[27] == redundancyB[27] &&
redundancyA[01] == redundancyB[01] && redundancyA[32] == redundancyB[32] &&
redundancyA[03] == redundancyB[03] && redundancyA[33] == redundancyB[33] &&
redundancyA[13] == redundancyB[13] && redundancyA[07] == redundancyB[07] )
{
//goto END;
}
for(i = 0; i < 36; i++)
{
redundancyB[i] = redundancyA[i];
}
//Setup for Second AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+48] = dibit;
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
// signaling data or sync
for(i = 0; i < 24; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+66] = dibit;
syncdata[(2*i)] = (1 & (dibit >> 1)); // bit 1
syncdata[(2*i)+1] = (1 & dibit); // bit 0
sync[i] = (dibit | 1) + 48;
if (i < 4 || i > 19) //
{
EmbeddedSignalling[2*i] = (1 & (dibit >> 1)); // bit 1
EmbeddedSignalling[2*i+1] = (1 & dibit); // bit 0
}
// load the superframe to do the voiceburstsync processing
if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E
{
/* Time slot 1 superframe buffer filling => SYNC data */
state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1
state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2+1] = (1 & dibit); // bit 0
}
if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E
{
/* Time slot 2 superframe buffer filling => SYNC data */
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;
EmbeddedSignallingOk = -1;
if(QR_16_7_6_decode(EmbeddedSignalling))
{
EmbeddedSignallingOk = 1;
}
internalcolorcode = 69; //set so we know if this value is being set properly
if(EmbeddedSignallingOk == 1)
{
state->color_code = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
internalcolorcode = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
state->color_code_ok = EmbeddedSignallingOk;
//Power Indicator, not the other PI (header)
state->PI = (unsigned int)EmbeddedSignalling[4];
state->PI_ok = EmbeddedSignallingOk;
//Link Control Start Stop Indicator
state->LCSS = (unsigned int)((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
state->LCSS_ok = EmbeddedSignallingOk;
}
//else skipcount++;
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+90] = dibit;
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
//WIP for RC inbound sync data, part 2, second 24 bits (12 dibits)
if (i <= 12)
{
rcsyncdata[i+12] = (dibit | 1) + 48; //test and double check positions for this sync data
}
}
//Setup for Third AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Third AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+108] = dibit;
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
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) ) //
{
if (internalslot == 0)
{
vc1 = 1;
fprintf (stderr, "MS Slot 1 Voice Sync \n");
//activeslot = 0;
}
if (internalslot == 1)
{
vc2 = 1;
//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
{
fprintf (stderr,"%s ", getTime());
if (internalslot == 0)
{
sprintf(state->slot1light, "[slot1]");
sprintf(state->slot2light, " slot2 ");
fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | RC ", state->color_code);
//test with vc1 reset disabled, if all is well, leave disabled
//vc1 = 1;
}
if (internalslot == 1)
{
sprintf(state->slot2light, "[slot2]");
sprintf(state->slot1light, " slot1 ");
fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | RC ", state->color_code);
//test with vc1 reset disabled, if all is well, leave disabled
//vc2 = 1;
}
fprintf (stderr, "\n "); //21 spaces to line up the sync
//processDMRdata (opts, state);
state->dmr_ms_rc = 1; //don't know what to do with this, if anything...
goto SKIP;
}
//check for sync pattern here after collected the rest of the payload, decide what to do with it
if ( (strcmp (sync, DMR_MS_DATA_SYNC) == 0) )
{
fprintf (stderr,"%s ", getTime());
if (internalslot == 0)
{
sprintf(state->slot1light, "[slot1]");
sprintf(state->slot2light, " slot2 ");
//fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | MS Data ", state->color_code);
fprintf (stderr,"Sync: +DMR ");
//test with vc1 reset disabled, if all is well, leave disabled
//vc1 = 1;
}
if (internalslot == 1)
{
sprintf(state->slot2light, "[slot2]");
sprintf(state->slot1light, " slot1 ");
//fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | Data ", state->color_code);
fprintf (stderr,"Sync: +DMR ");
//test with vc1 reset disabled, if all is well, leave disabled
//vc2 = 1;
}
//fprintf (stderr, "\n "); //21 spaces to line up the sync
//fprintf (stderr, " "); //21 spaces to line up the sync
state->dmr_ms_mode = 1; //set to 1 here??
processDMRdata (opts, state);
skipcount++;
//goto SKIP;
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)
{
skipcount = 0; //reset skip count if processing voice frames
fprintf (stderr,"%s ", getTime());
if (internalslot == 0)
{
fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc1);
}
if (internalslot == 1)
{
fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc2);
}
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");
}
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
if (internalslot == 0)
{
//vc1++;
}
if (internalslot == 1)
{
vc2++;
}
}
vc1++;
//6 seems optimal for MS, allows to quickly exit and resync if wonky or something
if ( (vc1 > 6) || skipcount > 2) //escape to find new sync if deadspins without a renewed voice frame sync inside of loop
{
goto END;
}
SKIP:
skipDibit (opts, state, 144); //skip to next slot?
state->dmr_ms_rc = 0;
//since we are in a repetitive loop, run ncursesPrinter here
if (opts->use_ncurses_terminal == 1)
{
ncursesPrinter(opts, state);
}
} // end while loop
//reset these variables when exiting MS mode.
END:
//get first half payload dibits and store them in the payload for the next repitition
skipDibit (opts, state, 144);
//CACH + First Half Payload = 12 + 54
for (i = 0; i < 66; i++) //66
{
dibit = getDibit(opts, state);
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i] = dibit;
//fprintf(stderr, "%X", state->dmr_stereo_payload[i]);
}
state->dmr_stereo = 0;
state->dmr_ms_mode = 0;
state->dmr_ms_rc = 0;
}
//Only process 2nd half voice payload (3rd frame) and then jump to full MS Voice decoding.
void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
{
int i, j, k, l, dibit;
int *dibit_p;
char ambe_fr[4][24] = {0};
char ambe_fr2[4][24] = {0};
char ambe_fr3[4][24] = {0};
const int *w, *x, *y, *z;
char sync[25];
char syncdata[48];
char cachdata[13] = {0};
int mutecurrentslot;
int msMode;
char cc[4];
unsigned char EmbeddedSignalling[16];
unsigned int EmbeddedSignallingOk;
//add time to mirror sync
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
{
time_t t = time(NULL);
char * curr;
char * stamp = asctime(localtime( & t));
curr = strtok(stamp, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
return curr;
}
state->dmrburstL = 16; //Use 16 for Voice?
dibit_p = state->dmr_payload_p - 90;
//payload buffer tests
//CACH + First Half Payload + Sync = 12 + 54 + 24
//fprintf(stderr, "\n Full DMR Stereo Dump Dibits 90 From Buffer\n");
for (i = 0; i < 90; i++) //90
{
state->dmr_stereo_payload[i] = *dibit_p;
dibit_p++;
//fprintf(stderr, "%X", state->dmr_stereo_payload[i]);
}
//end payload buffer test
for(i = 0; i < 12; i++)
{
dibit = state->dmr_stereo_payload[i];
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
}
//Setup for first AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//First AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = state->dmr_stereo_payload[i+12];
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
//state->dmr_stereo_payload[i+12] = dibit;
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//Setup for Second AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = state->dmr_stereo_payload[i+48];
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
for(i = 0; i < 18; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//Setup for Third AMBE Frame
//Interleave Schedule
w = rW;
x = rX;
y = rY;
z = rZ;
//Third AMBE Frame, Full 36
for(i = 0; i < 36; i++)
{
dibit = getDibit(opts, state);
if(opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
fprintf (stderr, "MS MODE ");
fprintf (stderr,"%s ", getTime());
fprintf (stderr,"Sync: +DMR | Color Code=XX | DMRSTEREO | VC1 FS \n");
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
}
void dmrMSData (dsd_opts * opts, dsd_state * state)
{
int i;
int dibit;
int *dibit_p;
unsigned int burst;
//add time to mirror sync
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
{
time_t t = time(NULL);
char * curr;
char * stamp = asctime(localtime( & t));
curr = strtok(stamp, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
curr = strtok(NULL, " ");
return curr;
}
//CACH + First Half Payload + Sync = 12 + 54 + 24
//fprintf(stderr, "\n Full DMR Stereo Dump Dibits 90 From Buffer\n");
for (i = 0; i < 90; i++) //90
{
//fprintf(stderr, "%X", state->dmr_stereo_payload[i]);
}
for (i = 0; i < 54; i++)
{
dibit = getDibit(opts, state);
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i+90] = dibit;
}
//fprintf(stderr, "\n");
//print nice pretty lines
fprintf (stderr, "MS MODE ");
fprintf (stderr, "%s ", getTime());
//fprintf (stderr, "Sync: +MS DATA | Color Code=XX | DMRSTEREO | Data ");
fprintf (stderr, "Sync: +DMR ");
//fprintf (stderr, "\n ");
//sprintf for slot 1, doesn't matter, just makes print out of data look uniform setting ahead of time
sprintf(state->slot1light, "[slot1]");
sprintf(state->slot2light, " slot2 ");
//process data
state->dmr_stereo = 1;
state->dmr_ms_mode = 1;
processDMRdata (opts, state);
state->dmr_stereo = 0;
state->dmr_ms_mode = 0;
//get potential first half payload dibits and store them in the payload for the next repitition, MS voice or data.
skipDibit (opts, state, 144);
//CACH + First Half Payload = 12 + 54
for (i = 0; i < 66; i++) //66
{
dibit = getDibit(opts, state);
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
state->dmr_stereo_payload[i] = dibit;
//fprintf(stderr, "%X", state->dmr_stereo_payload[i]);
}
}

View File

@@ -19,6 +19,26 @@
#include "dmr_const.h"
#include "p25p1_check_hdu.h"
//
//
void ProcessDMR (dsd_opts * opts, dsd_state * state)
{
uint32_t i, j;
uint32_t Frame;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameL = NULL;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameR = NULL;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameRC = NULL; //Reverse Test for MS Backwards
int *errs;
int *errs2;
unsigned long long int k;
int x;
k = 0;
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,
@@ -54,71 +74,53 @@ int BP[256] = {
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255
};
//
void ProcessDMR (dsd_opts * opts, dsd_state * state)
{
uint32_t i, j;
uint32_t Frame;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrame = NULL;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameL = NULL;
TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameR = NULL;
int *errs;
int *errs2;
int *errsR;
int *errs2R;
unsigned long long int k;
int x;
k = 0;
if(state->currentslot == 0)
{
TSVoiceSupFrame = &state->TS1SuperFrame;
}
else
{
TSVoiceSupFrame = &state->TS2SuperFrame;
}
//TSVoiceSupFrameL = &state->TS1SuperFrame;
//TSVoiceSupFrameR = &state->TS2SuperFrame;
//
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
if (state->currentslot == 0 && 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);
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++)
{
k = BP[state->K];
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
{
x = ( ((k << j) & 0x800000000000) >> 47 );
TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x;
}
TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x;
}
}
}
}
if (state->currentslot == 1 && state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0)
{
fprintf (stderr, "%s", KYEL);
fprintf(stderr, " BPK %lld", state->K);
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++)
{
x = ( ((k << j) & 0x800000000000) >> 47 );
TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x;
}
}
}
}
//
for(Frame = 0; Frame < 6; Frame++)
if (state->currentslot == 0)
{
for(Frame = 0; Frame < 6; Frame++) //6
{
/* 1 DMR frame contains 3 AMBE voice samples */
//fprintf (stderr, "\n 1AMBE ");
for(i = 0; i < 3; i++)
{
errs = (int*)&(TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
errs2 = (int*)&(TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs2[i]);
state->errs = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement
state->errs2 = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errs, errs2, state->err_str,
TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
/*
if (state->currentslot == 0)
{
errs = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
errs2 = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs2[i]);
state->errs = TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement
@@ -128,45 +130,16 @@ if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
state->debug_audio_errors += *errs2;
//state->debug_audio_errors += *errs2R;
processAudio(opts, state);
playSynthesizedVoice (opts, state);
}
if (state->currentslot == 1)
{
errsR = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
errs2R = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]);
state->errs = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement
state->errs2 = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement
//state->audio_out_temp_bufR = state->audio_out_temp_buf;
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errsR, errs2R, state->err_strR,
TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
state->debug_audio_errors += *errs2R;
processAudio(opts, state);
playSynthesizedVoice (opts, state);
}
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, errsR, errs2R, state->err_strR,
TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
*/
if (opts->mbe_out_f != NULL)
{
saveAmbe2450Data (opts, state, TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
saveAmbe2450Data (opts, state, TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
}
if (opts->errorbars == 1)
{
fprintf(stderr, "%s", state->err_str);
//fprintf(stderr, "%s", state->err_str);
}
state->debug_audio_errors += *errs2;
//state->debug_audio_errors += *errs2R;
processAudio(opts, state);
//playSynthesizedVoice (opts, state);
@@ -176,14 +149,59 @@ if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0)
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1 && opts->p25enc != 1) //play only if not equal to enc value, going to set p25enc to 1 if enc detected??
//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);
}
} /* End for(i = 0; i < 3; i++) */
} /* End for(Frame = 0; Frame < 6; Frame++) */
} /* End ProcessDMREncryption() */
} //End if Current Slot == 0
if (state->currentslot == 1)
{
for(Frame = 0; Frame < 6; Frame++)
{
/* 1 DMR frame contains 3 AMBE voice samples */
for(i = 0; i < 3; i++)
{
errs = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
errs2 = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]);
state->errs = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement
state->errs2 = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errs, errs2, state->err_str,
TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
if (opts->mbe_out_f != NULL)
{
saveAmbe2450Data (opts, state, TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]);
}
if (opts->errorbars == 1)
{
//fprintf(stderr, "%s", state->err_str);
}
state->debug_audio_errors += *errs2;
processAudio(opts, state);
//playSynthesizedVoice (opts, state);
if (opts->wav_out_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
//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);
}
} /* End for(i = 0; i < 3; i++) */
} /* End for(Frame = 0; Frame < 6; Frame++) */
} //End if Current Slot == 1
} /* End ProcessDMR */
/* End of file */

File diff suppressed because it is too large Load Diff

View File

@@ -115,10 +115,29 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
//method to only listen to a chosen slot when voices occupy both slots simultaneously
//method supersceeded by DMRSTEREO
//state->hardslot = 9; //0 to only listen to slot 0 voice, 1 for slot 1, 9 for both
//if(state->hardslot != 9 && state->hardslot != state->currentslot)
//if(1==1)
//{
//fprintf (stderr, " Current Slot = %d", state->currentslot + 1);
//fprintf (stderr, "\n"); //line break after breaking out of jail
//goto JUMP;
//}
}
}
cachdata[12] = 0;
//set state-dmrburstL and R here to a value for ncurses
if (state->currentslot == 0)
{
state->dmrburstL = 16; //use 16 for Voice?
}
if (state->currentslot == 1)
{
state->dmrburstR = 16; //Use 16 for Voice?
}
#ifdef DMR_DUMP
k = 0;
@@ -370,10 +389,23 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
sprintf(state->slot2light, "[sLoT2]");
}
if((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0))
//Comment out Below Lines, or switch if/else if if these cause issues.
/*
else if((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0))
{
msMode = 1;
if strcmp (sync, DMR_MS_VOICE_SYNC) == 0)
{
//quickDMRVoice (opts, state); //or make handler for msvoice seperate
//goto JUMP; //quit early when returned here
}
}
else if((strcmp (sync, DMR_BS_VOICE_SYNC) == 0)
{
//quickDMRVoice (opts, state); //or make handler for msvoice seperate
//goto JUMP; //quit early when returned here
}
*/
// TODO : To be removed
// if((j == 0) && (opts->errorbars == 1))
@@ -574,8 +606,9 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
fprintf(stderr, "%s ", syncbits);
#endif
if(j == 5)
if(j == 5) //j == 5
{
// 2nd half next slot
skipDibit (opts, state, 54);
@@ -617,6 +650,7 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
}
}
} /* End for(j = 0; j < 6; j++) */
if(opts->errorbars == 1)
@@ -624,14 +658,25 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
fprintf(stderr, "%s %s ", state->slot1light, state->slot2light);
/* Print the color code */
fprintf (stderr, "%s", KCYN);
fprintf(stderr, "| Color Code=%02d ", (int)state->color_code);
fprintf (stderr, "%s", KNRM);
//if(state->color_code_ok) fprintf(stderr, "(OK) |");
if(state->color_code_ok) fprintf(stderr, "(CRC OK ) |"); //add line break
else fprintf(stderr, "(CRC ERR) |"); //add line break
if(state->color_code_ok)
{
fprintf(stderr, "| (CRC OK ) |"); //add line break
state->dmr_color_code = state->color_code; //set here when voice? otherwise is set off of idle.
}
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, "| (CRC ERR) |"); //add line break
fprintf (stderr, "%s", KNRM);
}
//fprintf(stderr, " VOICE e: \n");
fprintf(stderr, " VOICE ");
fprintf(stderr, " VOICE ");
}
/* Perform the SYNC DMR data embedded decoding */
@@ -642,9 +687,10 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
/* Print DMR frame (if needed) */
//DMRVoiceFrameProcess(opts, state); //HERE HERE, was enabled, disabled so I could build
//JUMP:
if(opts->errorbars == 1)
{
fprintf(stderr, "\n");
}
} /* End processDMRvoice() */

View File

@@ -163,10 +163,10 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
{
dibit = getDibit (opts, state);
if (opts->inverted_dpmr == 1)
{
dibit = (dibit ^ 2);
}
if (opts->inverted_dpmr == 1)
{
dibit = (dibit ^ 2);
}
ambe_fr[j + 4][*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[j + 4][*y][*z] = (1 & dibit); // bit 0
@@ -467,13 +467,17 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
//fprintf(stderr, "| TG=%s", CalledID);
if(state->dPMRVoiceFS2Frame.CalledIDOk)
{
fprintf (stderr, "%s", KGRN);
fprintf(stderr, "\n| TG=%s", CalledID);
fprintf (stderr, "%s", KNRM);
//strcpy (state->dpmr_target_id, CalledID); //HERE HERE
state->dpmr_target_id = CalledID;
//fprintf(stderr, " (CRC OK) ");
if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1))
{
fprintf (stderr, "%s", KGRN);
fprintf(stderr, " | Color Code=%02d ", (int)state->dPMRVoiceFS2Frame.ColorCode[0]);
fprintf (stderr, "%s", KNRM);
state->dpmr_color_code = (int)state->dPMRVoiceFS2Frame.ColorCode[0];
}
@@ -488,15 +492,19 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
//fprintf(stderr, "| Src=%s", CallingID);
if(state->dPMRVoiceFS2Frame.CallingIDOk)
{
fprintf (stderr, "%s", KGRN);
fprintf(stderr, "| Src=%s", CallingID);
fprintf (stderr, "%s", KNRM);
//strcpy (state->dpmr_caller_id, CallingID);
state->dpmr_caller_id = CallingID;
fprintf(stderr, " (CRC OK) \n");
//fprintf(stderr, " (CRC OK) \n");
}
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, " (CRC ERR) \n");
fprintf (stderr, "%s", KNRM);
}
#endif /* (NB_OF_DPMR_VOICE_FRAME_TO_DECODE == 2) */
@@ -583,7 +591,7 @@ void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferO
LFSRValue >>= 1;
}
/* There are 72 bit to encrypt for voice and 288 bit for data */
/* There are 72 bit to descramble for voice and 288 bit for data */
for(i = 0; i < NbOfBitToScramble; i++)
{
BufferOut[i] = (BufferIn[i] ^ S[0]) & 0x01;
@@ -613,8 +621,8 @@ void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferO
} /* End ScrambleDPmrBit() */
/* Scrambler used for dPMR encryption / decryption,
* see ETSI TS 102 658 chapter 7.3 for the
/* Scrambler used for dPMR scrambling / descrambling,
* see ETSI TS 102 658 chapter 7.4 for the
* polynomial description.
* It is a X^9 + X^5 + 1 polynomial. */
void DeInterleave6x12DPmrBit(uint8_t * BufferIn, uint8_t * BufferOut)

View File

@@ -21,8 +21,6 @@ pa_sample_spec ss;
pa_sample_spec tt;
pa_sample_spec zz;
pa_sample_spec cc;
//pa_channel_map channel_map;
void openPulseOutput(dsd_opts * opts)
{
@@ -34,68 +32,39 @@ void openPulseOutput(dsd_opts * opts)
tt.format = PA_SAMPLE_S16NE;
tt.channels = opts->pulse_digi_out_channels; //doing tests with 2 channels at 22050 for 44100 audio default in pulse
tt.rate = opts->pulse_digi_rate_out; //48000, switches to 8000 when using RTL dongle
//fprintf (stderr,"digi rate out = %d\n", opts->pulse_digi_rate_out);
//pa_channel_map_init_stereo(&channel_map);
//ss
if (opts->monitor_input_audio == 1)
//if (opts->frame_dmr == 1 && opts->audio_in_type != 3)
{
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Raw Audio", &ss, NULL, NULL, NULL);
//opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO Right", &ss, NULL, NULL, NULL);
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Raw Audio Out", &ss, NULL, NULL, NULL);
}
//tt
pa_channel_map* left = 0; //NULL and 0 are same in this context
pa_channel_map* right = 0; //NULL and 0 are same in this context
//pa_channel_map* right;
//pa_channel_map_init(right);
opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, opts->output_name, &tt, left, NULL, NULL);
//opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD FME", PA_STREAM_PLAYBACK, NULL, "Digi Audio Out LEFT", &tt, left, NULL, NULL);
//opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Digi Audio Out RIGHT", &tt, right, NULL, NULL);
if (opts->dmr_stereo == 0)
{
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-FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO LEFT", &tt, left, NULL, NULL);
opts->pulse_digi_dev_outR = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO RIGHT", &tt, right, NULL, NULL);
}
}
void openPulseInput(dsd_opts * opts)
{
zz.format = PA_SAMPLE_S16NE;
zz.channels = opts->pulse_raw_in_channels;
zz.rate = opts->pulse_raw_rate_in; //48000
cc.format = PA_SAMPLE_S16NE;
cc.channels = opts->pulse_digi_in_channels;
cc.rate = opts->pulse_digi_rate_in; //48000
//zz
if (opts->monitor_input_audio == 1)
{
//opts->pulse_raw_dev_in = pa_simple_new(NULL, "DSD-FME", PA_STREAM_RECORD, NULL, "Raw Audio In", &zz, NULL, NULL, NULL);
}
//cc
opts->pulse_digi_dev_in = pa_simple_new(NULL, "DSD-FME", PA_STREAM_RECORD, NULL, opts->output_name, &cc, NULL, NULL, NULL);
}
//playRawAudio may be obsoleted now that I can run these correctly right inside of dsd_symbol
void playRawAudio(dsd_opts * opts, dsd_state * state)
{
short obuf, outl, i, sample2, something;
something = state->samplesPerSymbol / 1; //1 for buffer steal loops, 5 for rtl loop
//something = 1;
if (opts->audio_in_type == 0 && opts->audio_out_type == 0){ //hack, but might as well for this particular type since its nearly perfect
for (i=0; i < something; i++){
//read (opts->audio_in_fd, &sample2, 2); //reading here seems to get same speed as gfsk modulation
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
//pa_simple_read(opts->pulse_raw_dev_in, &state->pulse_raw_out_buffer, 2, NULL );
//obuf = state->pulse_raw_out_buffer / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping
//obuf = state->input_sample_buffer;
//obuf = state->pulse_raw_out_buffer;
//write (opts->audio_out_fd, (void*)&obuf, 2);
//pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, 2, NULL);
//pa_simple_write(opts->pulse_digi_dev_out, (void*)&obuf, 2, NULL);
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
}
}
} //end playRawAudio
void
processAudio (dsd_opts * opts, dsd_state * state)
@@ -109,7 +78,6 @@ processAudio (dsd_opts * opts, dsd_state * state)
// detect max level
max = 0;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
//state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
for (n = 0; n < 160; n++)
{
aout_abs = fabsf (*state->audio_out_temp_buf_p);
@@ -118,24 +86,18 @@ processAudio (dsd_opts * opts, dsd_state * state)
max = aout_abs;
}
state->audio_out_temp_buf_p++;
//state->audio_out_temp_buf_pR++;
}
*state->aout_max_buf_p = max;
//*state->aout_max_buf_pR = max;
state->aout_max_buf_p++;
//state->aout_max_buf_pR++;
state->aout_max_buf_idx++;
//state->aout_max_buf_idxR++;
if (state->aout_max_buf_idx > 24)
{
state->aout_max_buf_idx = 0;
state->aout_max_buf_p = state->aout_max_buf;
}
//if (state->aout_max_buf_idxR > 24)
// {
// state->aout_max_buf_idxR = 0;
// state->aout_max_buf_pR = state->aout_max_bufR;
// }
// lookup max history
for (i = 0; i < 25; i++)
@@ -194,7 +156,9 @@ processAudio (dsd_opts * opts, dsd_state * state)
// copy audio data to output buffer and upsample if necessary
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
if (opts->split == 0)
//we only want to upsample when using sample rates greater than 8k for output,
//hard set to 8k for RTL mono and MBE playback, otherwise crackling may occur.
if (opts->pulse_digi_rate_out > 8000)
{
for (n = 0; n < 160; n++)
{
@@ -241,6 +205,147 @@ processAudio (dsd_opts * opts, dsd_state * state)
state->audio_out_idx2++;
}
}
}
void
processAudioR (dsd_opts * opts, dsd_state * state)
{
int i, n;
float aout_abs, max, gainfactor, gaindelta, maxbuf;
if (opts->audio_gainR == (float) 0)
{
// detect max level
max = 0;
state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
for (n = 0; n < 160; n++)
{
aout_abs = fabsf (*state->audio_out_temp_buf_pR);
if (aout_abs > max)
{
max = aout_abs;
}
state->audio_out_temp_buf_pR++;
}
*state->aout_max_buf_pR = max;
state->aout_max_buf_pR++;
state->aout_max_buf_idxR++;
if (state->aout_max_buf_idxR > 24)
{
state->aout_max_buf_idxR = 0;
state->aout_max_buf_pR = state->aout_max_bufR;
}
// lookup max history
for (i = 0; i < 25; i++)
{
maxbuf = state->aout_max_bufR[i];
if (maxbuf > max)
{
max = maxbuf;
}
}
// determine optimal gain level
if (max > (float) 0)
{
gainfactor = ((float) 30000 / max);
}
else
{
gainfactor = (float) 50;
}
if (gainfactor < state->aout_gainR)
{
state->aout_gainR = gainfactor;
gaindelta = (float) 0;
}
else
{
if (gainfactor > (float) 50)
{
gainfactor = (float) 50;
}
gaindelta = gainfactor - state->aout_gainR;
if (gaindelta > ((float) 0.05 * state->aout_gainR))
{
gaindelta = ((float) 0.05 * state->aout_gainR);
}
}
gaindelta /= (float) 160;
}
else
{
gaindelta = (float) 0;
}
if(opts->audio_gainR >= 0)
{
// adjust output gain
state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
for (n = 0; n < 160; n++)
{
*state->audio_out_temp_buf_pR = (state->aout_gainR + ((float) n * gaindelta)) * (*state->audio_out_temp_buf_pR);
state->audio_out_temp_buf_pR++;
}
state->aout_gainR += ((float) 160 * gaindelta);
}
// copy audio data to output buffer and upsample if necessary
state->audio_out_temp_buf_pR = state->audio_out_temp_bufR;
//we only want to upsample when using sample rates greater than 8k for output,
//hard set to 8k for RTL mono and MBE playback, otherwise crackling may occur.
if (opts->pulse_digi_rate_out > 8000)
{
for (n = 0; n < 160; n++)
{
upsample (state, *state->audio_out_temp_buf_pR);
state->audio_out_temp_buf_pR++;
state->audio_out_float_buf_pR += 6;
state->audio_out_idxR += 6;
state->audio_out_idx2R += 6;
}
state->audio_out_float_buf_pR -= (960 + opts->playoffsetR);
// copy to output (short) buffer
for (n = 0; n < 960; n++)
{
if (*state->audio_out_float_buf_pR > 32767.0F)
{
*state->audio_out_float_buf_pR = 32767.0F;
}
else if (*state->audio_out_float_buf_pR < -32768.0F)
{
*state->audio_out_float_buf_pR = -32768.0F;
}
*state->audio_out_buf_pR = (short) *state->audio_out_float_buf_pR;
state->audio_out_buf_pR++;
state->audio_out_float_buf_pR++;
}
state->audio_out_float_buf_pR += opts->playoffsetR;
}
else
{
for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_pR > 32767.0F)
{
*state->audio_out_temp_buf_pR = 32767.0F;
}
else if (*state->audio_out_temp_buf_pR < -32768.0F)
{
*state->audio_out_temp_buf_pR = -32768.0F;
}
*state->audio_out_buf_pR = (short) *state->audio_out_temp_buf_pR;
state->audio_out_buf_pR++;
state->audio_out_temp_buf_pR++;
state->audio_out_idxR++;
state->audio_out_idx2R++;
}
}
}
void
@@ -250,10 +355,6 @@ writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
short aout_buf[160];
short *aout_buf_p;
// for(n=0; n<160; n++)
// fprintf (stderr,"%d ", ((short*)(state->audio_out_temp_buf))[n]);
// fprintf (stderr,"\n");
aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
@@ -274,34 +375,6 @@ writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
sf_write_short(opts->wav_out_f, aout_buf, 160);
/*
int n;
short aout_buf[160];
short *aout_buf_p;
ssize_t result;
aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_p > (float) 32760)
{
*state->audio_out_temp_buf_p = (float) 32760;
}
else if (*state->audio_out_temp_buf_p < (float) -32760)
{
*state->audio_out_temp_buf_p = (float) -32760;
}
*aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++;
state->audio_out_temp_buf_p++;
}
result = write (opts->wav_out_fd, aout_buf, 320);
fflush (opts->wav_out_f);
state->wav_out_bytes += 320;
*/
}
void
@@ -310,183 +383,90 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
ssize_t result;
if (state->audio_out_idx > opts->delay)
{
// output synthesized speech to sound card
{
// output synthesized speech to sound card
if(opts->audio_out_type == 2)
{
#ifdef USE_PORTAUDIO
PaError err = paNoError;
do
{
long available = Pa_GetStreamWriteAvailable( opts->audio_out_pa_stream );
if(available < 0)
err = available;
//fprintf (stderr,"Frames available: %d\n", available);
if( err != paNoError )
break;
if(available > SAMPLE_RATE_OUT * PA_LATENCY_OUT)
{
//It looks like this might not be needed for very small latencies. However, it's definitely needed for a bit larger ones.
//When PA_LATENCY_OUT == 0.500 I get output buffer underruns if I don't use this. With PA_LATENCY_OUT <= 0.100 I don't see those happen.
//But with PA_LATENCY_OUT < 0.100 I run the risk of choppy audio and stream errors.
fprintf (stderr,"\nSyncing voice output stream\n");
err = Pa_StopStream( opts->audio_out_pa_stream );
if( err != paNoError )
break;
}
err = Pa_IsStreamActive( opts->audio_out_pa_stream );
if(err == 0)
{
fprintf (stderr,"Start voice output stream\n");
err = Pa_StartStream( opts->audio_out_pa_stream );
}
else if(err == 1)
{
err = paNoError;
}
if( err != paNoError )
break;
err = Pa_WriteStream( opts->audio_out_pa_stream, (state->audio_out_buf_p - state->audio_out_idx), state->audio_out_idx );
if( err != paNoError )
break;
} while(0);
if( err != paNoError )
{
fprintf (stderr, "An error occured while using the portaudio output stream\n" );
fprintf (stderr, "Error number: %d\n", err );
fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
}
#endif
//go F yourself PA
}
else
if (opts->monitor_input_audio == 1){
//pa_simple_flush(opts->pulse_raw_dev_in, NULL);
//pa_simple_flush(opts->pulse_raw_dev_out, NULL);
//state->pulse_raw_out_buffer = 0;
//pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL);
{
//Test just sending it straight on since I think I've figured out the STDIN and RTL for Stereo
pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
state->audio_out_idx = 0;
}
}
//two slot audio testing, still need to seperate channels first internally, but this will play them out of different streams
/*
if(state->currentslot == 0 && opts->audio_in_type != 3)
//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.
}
if(state->currentslot == 1 && opts->audio_in_type != 3)
{
pa_simple_write(opts->pulse_raw_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works.
//pa_simple_write(opts->pulse_raw_dev_out, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works.
state->audio_out_idx = 0;
}
if (opts->audio_in_type == 3)
//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;
}
*/
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 (state->audio_out_idx2 >= 800000)
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
}
#ifdef USE_PORTAUDIO
int getPADevice(char* dev, int input, PaStream** stream)
void
playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state)
{
int devnum = atoi(dev + 3);
fprintf (stderr,"Using portaudio device %d.\n", devnum);
ssize_t result;
PaError err;
int numDevices = Pa_GetDeviceCount();
if( numDevices < 0 )
if (state->audio_out_idxR > opts->delay)
{
// output synthesized speech to sound card
if(opts->audio_out_type == 2)
{
//go F yourself PA
}
else
{
fprintf (stderr, "ERROR: Pa_GetDeviceCount returned 0x%x\n", numDevices );
err = numDevices;
goto error;
}
if( devnum >= numDevices)
{
fprintf (stderr, "ERROR: Requested device %d is larger than number of devices.\n", devnum );
return(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;
}
/*
//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;
}
*/
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo( devnum );
}
/* print device name */
#ifdef WIN32
{ /* Use wide char on windows, so we can show UTF-8 encoded device names */
wchar_t wideName[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, deviceInfo->name, -1, wideName, MAX_PATH-1);
wprintf ( L"Name = %s\n", wideName );
}
#else
fprintf (stderr, "Name = %s\n", deviceInfo->name );
#endif
if((input == 1) && (deviceInfo->maxInputChannels == 0))
{
fprintf (stderr, "ERROR: Requested device %d is not an input device.\n", devnum );
return(1);
}
if((input == 0) && (deviceInfo->maxOutputChannels == 0))
{
fprintf (stderr, "ERROR: Requested device %d is not an output device.\n", devnum );
return(1);
}
//Create stream parameters
PaStreamParameters parameters;
parameters.device = devnum;
parameters.channelCount = 1; /* mono */
parameters.sampleFormat = paInt16; //Shorts
parameters.suggestedLatency = (input == 1) ? PA_LATENCY_IN : PA_LATENCY_OUT;
parameters.hostApiSpecificStreamInfo = NULL;
//Open stream
err = Pa_OpenStream(
stream,
(input == 1) ? &parameters : NULL,
(input == 0) ? &parameters : NULL,
(input == 1) ? SAMPLE_RATE_IN : SAMPLE_RATE_OUT,
PA_FRAMES_PER_BUFFER,
paClipOff,
NULL /*callback*/,
NULL );
if( err != paNoError ) goto error;
return 0;
error:
fprintf (stderr, "An error occured while initializing a portaudio stream\n" );
fprintf (stderr, "Error number: %d\n", err );
fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
if (state->audio_out_idx2R >= 800000)
{
state->audio_out_float_buf_pR = state->audio_out_float_bufR + 100;
state->audio_out_buf_pR = state->audio_out_bufR + 100;
memset (state->audio_out_float_bufR, 0, 100 * sizeof (float));
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
state->audio_out_idx2R = 0;
}
}
#endif
void
openAudioOutDevice (dsd_opts * opts, int speed)
{
// get info of device/file
/*
if(strncmp(opts->audio_out_dev, "pulse", 5) == 0)
{
opts->audio_out_type == 0;
}
*/
if(strncmp(opts->audio_out_dev, "pa:", 3) == 0)
{
opts->audio_out_type = 2;
@@ -518,70 +498,6 @@ openAudioOutDevice (dsd_opts * opts, int speed)
fprintf (stderr,"Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev);
exit(1);
}
/*
#ifdef SOLARIS
sample_info_t aset, aget;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_out_dev);
//exit (1);
}
// get current
ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = speed;
aset.play.sample_rate = speed;
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
{
fprintf (stderr,"Error setting sample device parameters\n");
exit (1);
}
#endif
#if defined(BSD) && !defined(__APPLE__)
int fmt;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_out_dev);
opts->audio_out = 0;
//exit(1);
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf (stderr,"ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf (stderr,"ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf (stderr,"ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf (stderr,"ioctl setfmt error \n");
}
#endif
*/
}
fprintf (stderr,"Audio Out Device: %s\n", opts->audio_out_dev);
}
@@ -661,90 +577,8 @@ openAudioInDevice (dsd_opts * opts)
{
// this is a device, use old handling, pulse audio now
opts->audio_in_type = 0;
/*
#ifdef SOLARIS
sample_info_t aset, aget;
int rgain;
rgain = 64;
if (opts->split == 1)
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
}
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
//exit(1);
}
// get current
ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = SAMPLE_RATE_IN;
aset.play.sample_rate = SAMPLE_RATE_IN;
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
aset.record.port = AUDIO_LINE_IN;
aset.record.gain = rgain;
if (ioctl (opts->audio_in_fd, AUDIO_SETINFO, &aset) == -1)
{
fprintf (stderr,"Error setting sample device parameters\n");
exit (1);
}
#endif
*/
/*
#if defined(BSD) && !defined(__APPLE__)
int fmt;
if (opts->split == 1)
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
}
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
opts->audio_out = 0;
}
fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf (stderr,"ioctl reset error \n");
}
fmt = SAMPLE_RATE_IN;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf (stderr,"ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf (stderr,"ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf (stderr,"ioctl setfmt error \n");
}
#endif
*/
}
}
}
if (opts->split == 1)

View File

@@ -185,9 +185,16 @@ use_symbol (dsd_opts* opts, dsd_state* state, int symbol)
}
if (state->dibit_buf_p > state->dibit_buf + 900000)
{
state->dibit_buf_p = state->dibit_buf + 200;
}
{
state->dibit_buf_p = state->dibit_buf + 200;
}
//dmr buffer
if (state->dmr_payload_p > state->dmr_payload_buf + 900000)
{
state->dmr_payload_p = state->dmr_payload_buf + 200;
}
//dmr buffer end
}
static int
@@ -211,6 +218,7 @@ invert_dibit(int dibit)
}
static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
//int digitize (dsd_opts* opts, dsd_state* state, int symbol)
{
// determine dibit state
if ((state->synctype == 6) || (state->synctype == 14)|| (state->synctype == 18))
@@ -252,8 +260,10 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
return (0); // +1
}
}
else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) ||
(state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) || (state->synctype == 17))
(state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) ||
(state->synctype == 17) )
{
// 1 -P25p1
@@ -263,7 +273,6 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
// 11 -DMR (inverted signal voice frame)
// 13 -DMR (inverted signal data frame)
// 17 -NXDN (inverted data frame)
//
int valid;
int dibit;
@@ -361,64 +370,12 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
}
state->last_dibit = dibit;
//test loading up a shift register and printing it to stderr
//di-bit shift register for hex values
//check for which dibit is equal to which half-nibble
if (dibit == 0){state->hexbuf = 0x0;} //+1
if (dibit == 1){state->hexbuf = 0x1;} //+3
if (dibit == 2){state->hexbuf = 0x2;} //-1
if (dibit == 3){state->hexbuf = 0x3;} //-3
state->sr_0 = (state->sr_0 << 2) | (state->sr_1 >> 62);
state->sr_1 = (state->sr_1 << 2) | (state->sr_2 >> 62);
state->sr_2 = (state->sr_2 << 2) | (state->sr_3 >> 62);
state->sr_3 = (state->sr_3 << 2) | (state->sr_4 >> 62);
state->sr_4 = (state->sr_4 << 2) | (state->sr_5 >> 62);
state->sr_5 = (state->sr_5 << 2) | (state->sr_6 >> 62);
state->sr_6 = state->sr_6 << 2;
state->sr_6 |= state->hexbuf;
if (1 == 2) //disable this later on
{
fprintf (stderr, "\nsr_0 = %16llX \n", state->sr_0);
fprintf (stderr, "sr_1 = %16llX \n", state->sr_1);
fprintf (stderr, "sr_2 = %16llX \n", state->sr_2);
fprintf (stderr, "sr_3 = %16llX \n", state->sr_3);
fprintf (stderr, "sr_4 = %16llX \n", state->sr_4);
fprintf (stderr, "sr_5 = %16llX \n", state->sr_5);
fprintf (stderr, "sr_6 = %16llX \n", state->sr_6);
/*
printw ("sr_0 = %16llX \n", sr_0);
printw ("sr_1 = %16llX \n", sr_1);
printw ("sr_2 = %16llX \n", sr_2);
printw ("sr_3 = %16llX \n", sr_3);
printw ("sr_4 = %16llX \n", sr_4);
printw ("sr_5 = %16llX \n", sr_5);
printw ("sr_6 = %16llX \n", sr_6);
*/
}
if ( state->sr_5 & 0xFFFFF == 0xDDF5D) //disable this later on
{
fprintf (stderr, "\nsr_0 = %16llX \n", state->sr_0);
fprintf (stderr, "sr_1 = %16llX \n", state->sr_1);
fprintf (stderr, "sr_2 = %16llX \n", state->sr_2);
fprintf (stderr, "sr_3 = %16llX \n", state->sr_3);
fprintf (stderr, "sr_4 = %16llX \n", state->sr_4);
fprintf (stderr, "sr_5 = %16llX \n", state->sr_5);
fprintf (stderr, "sr_6 = %16llX \n", state->sr_6);
/*
printw ("sr_0 = %16llX \n", sr_0);
printw ("sr_1 = %16llX \n", sr_1);
printw ("sr_2 = %16llX \n", sr_2);
printw ("sr_3 = %16llX \n", sr_3);
printw ("sr_4 = %16llX \n", sr_4);
printw ("sr_5 = %16llX \n", sr_5);
printw ("sr_6 = %16llX \n", sr_6);
*/
}
*state->dibit_buf_p = dibit;
state->dibit_buf_p++;
//dmr buffer
*state->dmr_payload_p = dibit;
state->dmr_payload_p++;
//dmr buffer end
return dibit;
}
}
@@ -447,9 +404,7 @@ get_dibit_and_analog_signal (dsd_opts* opts, dsd_state* state, int* out_analog_s
//
state->sbuf[state->sidx] = symbol;
//
//state->pulse_raw_out_buffer = symbol;
//
if (out_analog_signal != NULL)
{
*out_analog_signal = symbol;

View File

@@ -76,7 +76,6 @@ saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
for (i = 0; i < 7; i++) //using 7 seems to break older amb files where it was 6, need to test 7 on 7 some more
{
b = 0;
for (j = 0; j < 8; j++)
{
b = b << 1;

View File

@@ -35,14 +35,20 @@ printFrameInfo (dsd_opts * opts, dsd_state * state)
}
if (state->nac != 0)
{
fprintf (stderr, "%s", KCYN);
fprintf (stderr,"nac: [%4X] ", state->nac);
fprintf (stderr, "%s", KNRM);
}
if (opts->verbose > 1)
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr,"src: [%8i] ", state->lastsrc);
fprintf (stderr, "%s", KNRM);
}
fprintf (stderr, "%s", KGRN);
fprintf (stderr,"tg: [%5i] ", state->lasttg);
fprintf (stderr, "%s", KNRM);
}
void
@@ -168,12 +174,15 @@ processFrame (dsd_opts * opts, dsd_state * state)
processDSTAR_HD (opts, state);
return;
}
else if ((state->synctype >= 10) && (state->synctype <= 13))
//Start DMR Types
else if ((state->synctype >= 10) && (state->synctype <= 13) || (state->synctype == 32) || (state->synctype == 33) || (state->synctype == 34) ) //32-34 DMR MS and RC
{
//disable so radio id doesn't blink in and out during ncurses and aggressive_framesync
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
//state->lastsrc = 0;
//state->lasttg = 0;
//state->lastsrcR = 0;
//state->lasttgR = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
@@ -182,21 +191,63 @@ processFrame (dsd_opts * opts, dsd_state * state)
//fprintf (stderr,"inlvl: %2i%% ", level);
}
}
if ((state->synctype == 11) || (state->synctype == 12))
if ( (state->synctype == 11) || (state->synctype == 12) || (state->synctype == 32) ) //DMR Voice Modes
{
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL) && opts->dmr_stereo == 0)
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processDMRvoice (opts, state);
if (opts->dmr_stereo == 0 && state->synctype < 32) // -T option for DMR (TDMA) stereo
{
processDMRvoice (opts, state);
}
if (opts->dmr_stereo == 0 && state->synctype == 32)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, "Please use the -T option to handle MS Mode with DMR Stereo TDMA Handling\n");
fprintf (stderr, "%s", KNRM);
}
if (opts->dmr_stereo == 1)
{
state->dmr_stereo = 1; //set the state to 1 when handling pure voice frames
if (state->synctype > 31 )
{
dmrMSBootstrap (opts, state); //bootstrap into MS Bootstrap (voice only)
}
else dmrBSBootstrap (opts, state); //bootstrap into BS Bootstrap
}
}
else if ( (state->synctype == 33) || (state->synctype == 34) ) //MS Data and RC data
{
if (opts->dmr_stereo == 0)
{
closeMbeOutFile (opts, state);
state->err_str[0] = 0;
fprintf (stderr, "%s", KRED);
fprintf (stderr, "Please use the -T option to handle MS Mode with DMR Stereo TDMA Handling\n");
fprintf (stderr, "%s", KNRM);
}
if (opts->dmr_stereo == 1)
{
dmrMSData (opts, state);
}
}
else
{
if (opts->dmr_stereo == 0)
{
closeMbeOutFile (opts, state);
state->err_str[0] = 0;
processDMRdata (opts, state);
}
//switch dmr_stereo to 0 when handling BS data frame syncs with processDMRdata
if (opts->dmr_stereo == 1)
{
state->dmr_stereo = 0; //set the state to zero for handling pure data frames
processDMRdata (opts, state);
}
}
return;
}
else if ((state->synctype >= 2) && (state->synctype <= 5))
@@ -244,7 +295,20 @@ processFrame (dsd_opts * opts, dsd_state * state)
processProVoice (opts, state);
return;
}
//LEH dPMR
//ysf
else if ((state->synctype == 30) || (state->synctype == 31))
{
//Do stuff
//fprintf(stderr, "YSF Sync! \n");
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
//openMbeOutFile (opts, state);
}
//sprintf(state->fsubtype, " VOICE ");
processYSF(opts, state);
return;
}
//dPMR
else if ((state->synctype == 20) || (state->synctype == 24))
{
/* dPMR Frame Sync 1 */
@@ -255,7 +319,6 @@ processFrame (dsd_opts * opts, dsd_state * state)
/* dPMR Frame Sync 2 */
fprintf(stderr, "dPMR Frame Sync 2 ");
//state->rf_mod = GFSK_MODE;
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
@@ -264,7 +327,6 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//fprintf(stderr, "inlvl: %2i%% ", level);
}
}
state->nac = 0;
@@ -290,7 +352,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
fprintf(stderr, "dPMR Frame Sync 4 ");
}
//dPMR
else
else //P25
{
// Read the NAC, 12 bits
j = 0;

View File

@@ -17,9 +17,8 @@
#include "dsd.h"
#include <locale.h>
//#include <ncurses.h>
//borrowed from LEH for 'improved NXDN sync detection'
//borrowed from DSDcc for 'improved NXDN sync detection'
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr)
{
int Compare = -1;
@@ -50,7 +49,6 @@ int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr)
return Compare;
} /* End strncmperr() */
//end LEH
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
@@ -140,15 +138,21 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
* 26 = -dPMR Frame Sync 3
* 27 = -dPMR Frame Sync 4
* 28 = +NXDN (sync only)
* 29 = -NXDN (sync only
* 29 = -NXDN (sync only)
* 30 = +YSF
* 31 = -YSF
* 32 = DMR MS Voice
* 33 = DMR MS Data
* 34 = DMR RC Data
*/
int i, j, t, o, dibit, sync, symbol, synctest_pos, lastt;
char synctest[25];
char synctest12[13]; //LEH DPMR
char synctest12[13]; //dPMR
char synctest18[19];
char synctest32[33];
char synctest20[21]; //YSF
char modulation[8];
char *synctest_p;
char synctest_buf[10240];
@@ -169,6 +173,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
synctest12[12] = 0;
synctest18[18] = 0;
synctest32[32] = 0;
synctest20[20] = 0;
synctest_pos = 0;
synctest_p = synctest_buf + 10;
sync = 0;
@@ -246,9 +251,9 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
if (state->dibit_buf_p > state->dibit_buf + 900000)
{
state->dibit_buf_p = state->dibit_buf + 200;
}
{
state->dibit_buf_p = state->dibit_buf + 200;
}
//determine dibit state
if (symbol > 0)
@@ -264,6 +269,49 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
dibit = 51; // '3'
}
//digitize test for storing dibits in buffer correctly for dmr recovery
if (state->dmr_payload_p > state->dmr_payload_buf + 900000)
{
state->dmr_payload_p = state->dmr_payload_buf + 200;
}
int valid;
//running estimate_symbol causes an issue with P25 syncing properly
if (opts->frame_p25p1 != 1)
{
valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit);
}
if (opts->frame_dmr == 1 && valid == 0) //opts->dmr_stereo
{
if (symbol > state->center)
{
if (symbol > state->umid)
{
*state->dmr_payload_p = 1; // +3
}
else
{
*state->dmr_payload_p = 0; // +1
}
}
else
{
if (symbol < state->lmid)
{
*state->dmr_payload_p = 3; // -3
}
else
{
*state->dmr_payload_p = 2; // -1
}
}
state->dmr_payload_p++;
}
// end digitize and dmr buffer testing
*synctest_p = dibit;
if (t >= 18)
{
@@ -502,7 +550,53 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
}
}
//YSF sync
strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
{
if (0 == 0) //opts->inverted_ysf == 0
{
if (strcmp(synctest20, FUSION_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
fprintf (stderr, "\nYSF FUSION SYNC \n");
opts->inverted_ysf = 0; //should we set this here?
state->lastsynctype = 30;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (30);
}
}
}
if(opts->frame_ysf == 1) //(opts->frame_ysf == 1
{
if (0 == 0) //opts->inverted_ysf == 1
{
if (strcmp(synctest20, INV_FUSION_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
fprintf (stderr, "\nINVERTED YSF FUSION SYNC \n");
opts->inverted_ysf = 1; //should we set this here?
state->lastsynctype = 31;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (31);
}
}
}
//end YSF sync
//dPMR sync
strncpy(synctest, (synctest_p - 23), 24);
strncpy(synctest12, (synctest_p - 11), 12);
@@ -512,7 +606,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
if(strcmp(synctest, DPMR_FRAME_SYNC_1) == 0)
{
fprintf (stderr, "+dPMR FS1\n");
//fprintf (stderr, "+dPMR FS1\n");
}
if(strcmp(synctest12, DPMR_FRAME_SYNC_2) == 0)
{
@@ -528,22 +622,26 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+dPMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 21;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (21);
}
if(strcmp(synctest12, DPMR_FRAME_SYNC_3) == 0)
{
fprintf (stderr, "+dPMR FS3 \n");
//fprintf (stderr, "+dPMR FS3 \n");
}
if(strcmp(synctest, DPMR_FRAME_SYNC_4) == 0)
{
fprintf (stderr, "+dPMR FS4 \n");
//fprintf (stderr, "+dPMR FS4 \n");
}
}
if (opts->inverted_dpmr == 1)
{
if(strcmp(synctest, INV_DPMR_FRAME_SYNC_1) == 0)
{
fprintf (stderr, "-dPMR FS1 \n");
//fprintf (stderr, "-dPMR FS1 \n");
}
if(strcmp(synctest12, INV_DPMR_FRAME_SYNC_2) == 0)
{
@@ -560,15 +658,19 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
state->lastsynctype = 25;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (25);
}
if(strcmp(synctest12, INV_DPMR_FRAME_SYNC_3) == 0)
{
fprintf (stderr, "-dPMR FS3 \n");
//fprintf (stderr, "-dPMR FS3 \n");
}
if(strcmp(synctest, INV_DPMR_FRAME_SYNC_4) == 0)
{
fprintf (stderr, "-dPMR FS4 \n");
//fprintf (stderr, "-dPMR FS4 \n");
}
}
}
@@ -576,7 +678,97 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//New DMR Sync
if (opts->frame_dmr == 1)
{
if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0))
if(strcmp (synctest, DMR_MS_DATA_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
//state->directmode = 0;
//fprintf (stderr, "DMR MS Data");
if (0 == 0) //opts->inverted_dmr
{
// data frame
sprintf(state->ftype, "DMR MS");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "+DMR MS Data", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 33) //33
{
//state->firstframe = 1;
}
state->lastsynctype = 33; //33
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (33); //33
}
}
//not sure if this should be here, RC data should only be present in vc6?
if(strcmp (synctest, DMR_RC_DATA_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
//state->directmode = 0;
//fprintf (stderr, "DMR RC DATA\n");
state->dmr_ms_rc == 1; //set flag for RC data, then process accordingly and reset back to 0 afterwards
if (0 == 0) //opts->inverted_dmr
{
// voice frame
sprintf(state->ftype, "DMR RC");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "+DMR RC Data", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 34)
{
//state->firstframe = 1;
}
state->lastsynctype = 34;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (34);
}
}
if(strcmp (synctest, DMR_MS_VOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
//state->directmode = 0;
//fprintf (stderr, "DMR MS VOICE\n");
if (0 == 0) //opts->inverted_dmr
{
// voice frame
sprintf(state->ftype, "DMR MS");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "+DMR MS Voice", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 32)
{
//state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (32);
}
}
//if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0))
if (strcmp (synctest, DMR_BS_DATA_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -594,7 +786,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 10;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (10);
@@ -614,7 +805,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 11;
if ( opts->monitor_input_audio == 1)
{
pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (11);
}
@@ -638,7 +829,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 10;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (10);
@@ -658,7 +848,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 11;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (11);
@@ -683,7 +872,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 10;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (10);
@@ -692,7 +880,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
// inverted voice frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
@@ -703,13 +891,13 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 11;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (11);
}
} /* End if(strcmp (synctest, DMR_DIRECT_MODE_TS2_DATA_SYNC) == 0) */
if((strcmp (synctest, DMR_MS_VOICE_SYNC) == 0) || (strcmp (synctest, DMR_BS_VOICE_SYNC) == 0))
//if((strcmp (synctest, DMR_MS_VOICE_SYNC) == 0) || (strcmp (synctest, DMR_BS_VOICE_SYNC) == 0))
if(strcmp (synctest, DMR_BS_VOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -720,7 +908,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
// voice frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation);
}
@@ -729,20 +917,24 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 12;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (12);
}
else
{
// inverted data frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 13;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (13);
@@ -756,7 +948,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->min = ((state->min) + lmin) / 2;
state->currentslot = 0;
state->directmode = 1; //Direct mode
if (opts->inverted_dmr == 0)
if (opts->inverted_dmr == 0 && opts->dmr_stereo == 0)
{
// voice frame
sprintf(state->ftype, "DMR ");
@@ -771,7 +963,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 12;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (12);
@@ -780,7 +971,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
// inverted data frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
@@ -800,7 +991,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
// voice frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation);
}
@@ -811,7 +1002,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 12;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (12);
@@ -820,14 +1010,14 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
// inverted data frame
sprintf(state->ftype, "DMR ");
if (opts->errorbars == 1)
if (opts->errorbars == 1 && opts->dmr_stereo == 0)
{
printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 13;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (13);
@@ -835,7 +1025,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
} //End if(strcmp (synctest, DMR_DIRECT_MODE_TS2_VOICE_SYNC) == 0)
} //End if (opts->frame_dmr == 1)
//end LEH DMR Sync
//end DMR Sync
if (opts->frame_provoice == 1)
{
strncpy (synctest32, (synctest_p - 31), 32);
@@ -855,7 +1045,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 14;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (14);
@@ -875,7 +1065,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 15;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (15);
@@ -885,8 +1075,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
{
strncpy (synctest18, (synctest_p - 17), 18);
//if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0)) //or is this the double up test?
//borrowing from LEH here WOW! This works so much better, its not even a joke
if ((strncmperr (synctest18, NXDN_BS_VOICE_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_VOICE_SYNC, 18, 1) == 0))
{
now = time(NULL);
@@ -903,7 +1091,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
sprintf (state->ftype, "NXDN48 "); //get rid of spaces
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
if (opts->errorbars == 1)
@@ -917,7 +1105,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
sprintf (state->ftype, "NXDN96");
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
if (opts->errorbars == 1)
@@ -967,7 +1155,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 9;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (9);
@@ -1009,7 +1197,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 16;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (16);
@@ -1052,7 +1240,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 17;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (17);
@@ -1082,7 +1270,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 6;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (6);
@@ -1102,7 +1290,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 7;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (7);
@@ -1122,7 +1310,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 18;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (18);
@@ -1142,7 +1330,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 19;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (19);
@@ -1212,7 +1400,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
return (4);
}
else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) || (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0)))
//dmr desync handling, causes issues with TDMA stereo (MS especially), consider removing
//may have been because we had BS Voice twice on here, seems okay, continue testing
/*
else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) ))
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -1221,17 +1413,18 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation);
//printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (11);
}
else if ((state->lastsynctype == 12) && ((strcmp (synctest, DMR_BS_DATA_SYNC) != 0) || (strcmp (synctest, DMR_MS_DATA_SYNC) != 0)))
*/
else if ( (state->lastsynctype == 32) && (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0) )
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -1240,18 +1433,76 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation);
//printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
if ( opts->monitor_input_audio == 1)
{
//pa_simple_drain(opts->pulse_raw_dev_out, NULL);
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (12);
return (32); //32
}
}
}
else if ( (state->lastsynctype == 33) && (strcmp (synctest, DMR_MS_DATA_SYNC) != 0) )
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (33); //33
}
else if ( (state->lastsynctype == 34) && (strcmp (synctest, DMR_RC_DATA_SYNC) != 0) )
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (34); //34
}
else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) ))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
//printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (11); //11
}
//DMR desync
} //if t == 24
} // t >= 18
if (exitflag == 1)
{
@@ -1294,12 +1545,9 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
return (-1);
}
}
if ( opts->monitor_input_audio == 1 && (time(NULL) - now) > 1 ) //okay, still something going on, latency issues
//if ( opts->monitor_input_audio == 1)
{
//playRawAudio(opts, state); //this is on line 21 in dsd_audio.c
}
}
return (-1);
}
//1111

View File

@@ -26,17 +26,6 @@
#include "provoice_const.h"
#include "git_ver.h"
//pretty pretty colors
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
int pretty_colors()
{
fprintf (stderr,"%sred\n", KRED);
@@ -84,6 +73,10 @@ noCarrier (dsd_opts * opts, dsd_state * state)
{
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
//dmr buffer
state->dmr_payload_p = state->dibit_buf + 200;
memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
//dmr buffer end
if (opts->mbe_out_f != NULL)
{
closeMbeOutFile (opts, state);
@@ -93,15 +86,18 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->carrier = 0;
state->max = 15000;
state->min = -15000;
state->center = 0;
state->center = 0; //quick disable for dmr testing with buffer
state->err_str[0] = 0;
state->err_strR[0] = 0;
sprintf (state->fsubtype, " ");
sprintf (state->ftype, " ");
state->errs = 0;
state->errs2 = 0;
//should I disable this or not?
state->lasttg = 0;
state->lastsrc = 0;
state->lasttgR = 0;
state->lastsrcR = 0;
state->lastp25type = 0;
state->repeat = 0;
state->nac = 0;
@@ -110,15 +106,26 @@ noCarrier (dsd_opts * opts, dsd_state * state)
sprintf (state->slot1light, " slot1 ");
state->firstframe = 0;
if (opts->audio_gain == (float) 0)
{
state->aout_gain = 25;
}
{
state->aout_gain = 25;
}
if (opts->audio_gainR == (float) 0)
{
state->aout_gainR = 25;
}
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
memset (state->aout_max_bufR, 0, sizeof (float) * 200);
state->aout_max_buf_pR = state->aout_max_bufR;
state->aout_max_buf_idxR = 0;
sprintf (state->algid, "________");
sprintf (state->keyid, "________________");
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
mbe_initMbeParms (state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2);
}
void
@@ -151,11 +158,13 @@ initOpts (dsd_opts * opts)
#endif
opts->split = 0;
opts->playoffset = 0;
opts->playoffsetR = 0;
opts->mbe_out_dir[0] = 0;
opts->mbe_out_file[0] = 0;
opts->mbe_out_path[0] = 0;
opts->mbe_out_f = NULL;
opts->audio_gain = 0;
opts->audio_gainR = 0;
opts->audio_out = 1;
opts->wav_out_file[0] = 0;
opts->wav_out_f = NULL;
@@ -163,7 +172,7 @@ initOpts (dsd_opts * opts)
opts->serial_baud = 115200;
sprintf (opts->serial_dev, "/dev/ttyUSB0");
opts->resume = 0;
opts->frame_dstar = 1;
opts->frame_dstar = 1;
opts->frame_x2tdma = 1;
opts->frame_p25p1 = 1;
opts->frame_nxdn48 = 0;
@@ -200,13 +209,16 @@ initOpts (dsd_opts * opts)
opts->pulse_digi_in_channels = 1; //2
opts->pulse_digi_out_channels = 1; //2
sprintf (opts->output_name, "Default Channel");
sprintf (opts->output_name, "Auto Detect");
opts->pulse_flush = 1; //set 0 to flush, 1 for flushed
opts->use_ncurses_terminal = 0;
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
//opts->audio_in_type = 0;
}
void
@@ -218,13 +230,18 @@ initState (dsd_state * state)
state->dibit_buf = malloc (sizeof (int) * 1000000);
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
//dmr buffer -- double check this set up
state->dmr_payload_buf = malloc (sizeof (int) * 1000000);
state->dmr_payload_p = state->dmr_payload_buf + 200;
memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
//dmr buffer end
state->repeat = 0;
state->audio_out_buf = malloc (sizeof (short) * 1000000);
state->audio_out_bufR = malloc (sizeof (short) * 1000000);
memset (state->audio_out_buf, 0, 100 * sizeof (short));
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
state->audio_out_buf_p = state->audio_out_buf + 100;
state->audio_out_buf_pR = state->audio_out_buf + 100;
state->audio_out_buf_pR = state->audio_out_bufR + 100;
state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
state->audio_out_float_bufR = malloc (sizeof (float) * 1000000);
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
@@ -296,6 +313,11 @@ initState (dsd_state * state)
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
memset (state->aout_max_bufR, 0, sizeof (float) * 200);
state->aout_max_buf_pR = state->aout_max_bufR;
state->aout_max_buf_idxR = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (state->algid, "________");
@@ -304,10 +326,17 @@ initState (dsd_state * state)
state->cur_mp = malloc (sizeof (mbe_parms));
state->prev_mp = malloc (sizeof (mbe_parms));
state->prev_mp_enhanced = malloc (sizeof (mbe_parms));
state->cur_mp2 = malloc (sizeof (mbe_parms));
state->prev_mp2 = malloc (sizeof (mbe_parms));
state->prev_mp_enhanced2 = malloc (sizeof (mbe_parms));
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
mbe_initMbeParms (state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2);
state->p25kid = 0;
state->debug_audio_errors = 0;
state->debug_audio_errorsR = 0;
state->debug_header_errors = 0;
state->debug_header_critical_errors = 0;
@@ -322,24 +351,51 @@ initState (dsd_state * state)
state->dpmr_caller_id = 0;
state->dpmr_target_id = 0;
state->payload_mi = 0;
state->payload_mi = 0;
state->payload_miR = 0;
state->payload_mfid = 0;
state->payload_mfidR = 0;
state->payload_algid = 0;
state->payload_algidR = 0;
state->payload_keyid = 0;
state->payload_keyidR = 0;
sprintf (state->dmr_branding, " ");
sprintf (state->dmr_callsign[0], "");
sprintf (state->dmr_callsign[1], "");
sprintf (state->dmr_callsign[2], "");
sprintf (state->dmr_callsign[3], "");
sprintf (state->dmr_lrrp[0], "");
sprintf (state->dmr_lrrp[1], "");
sprintf (state->dmr_lrrp[2], "");
sprintf (state->dmr_lrrp[3], "");
sprintf (state->dmr_lrrp[4], "");
sprintf (state->dmr_lrrp[5], "");
sprintf (state->dmr_callsign[0][0], "");
sprintf (state->dmr_callsign[0][1], "");
sprintf (state->dmr_callsign[0][2], "");
sprintf (state->dmr_callsign[0][3], "");
sprintf (state->dmr_callsign[0][4], "");
sprintf (state->dmr_callsign[0][5], "");
sprintf (state->dmr_callsign[1][0], "");
sprintf (state->dmr_callsign[1][1], "");
sprintf (state->dmr_callsign[1][2], "");
sprintf (state->dmr_callsign[1][3], "");
sprintf (state->dmr_callsign[1][4], "");
sprintf (state->dmr_callsign[1][5], "");
sprintf (state->dmr_lrrp[0][0], "");
sprintf (state->dmr_lrrp[0][1], "");
sprintf (state->dmr_lrrp[0][2], "");
sprintf (state->dmr_lrrp[0][3], "");
sprintf (state->dmr_lrrp[0][4], "");
sprintf (state->dmr_lrrp[0][5], "");
sprintf (state->dmr_lrrp[1][0], "");
sprintf (state->dmr_lrrp[1][1], "");
sprintf (state->dmr_lrrp[1][2], "");
sprintf (state->dmr_lrrp[1][3], "");
sprintf (state->dmr_lrrp[1][4], "");
sprintf (state->dmr_lrrp[1][5], "");
state->K = 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
state->dmr_so = 0;
state->dmr_soR = 0;
state->dmr_fid = 0;
state->dmr_fidR = 0;
memset(state->dstarradioheader, 0, 41);
#ifdef TRACE_DSD
state->debug_sample_index = 0;
@@ -380,7 +436,7 @@ usage ()
fprintf (stderr," -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
fprintf (stderr," -w <file> Output synthesized speech to a .wav file\n");
//fprintf (stderr," -a Display port audio devices\n");
//fprintf (stderr," -W Monitor Source Audio When No Sync Detected (WIP!)\n");
fprintf (stderr," -W Monitor Source Audio When No Sync Detected (WIP!)\n");
fprintf (stderr,"\n");
fprintf (stderr,"RTL-SDR options:\n");
fprintf (stderr," -c <hertz> RTL-SDR Frequency\n");
@@ -427,8 +483,14 @@ usage ()
fprintf (stderr," -M <num> Min/Max buffer size for QPSK decision point tracking\n");
fprintf (stderr," (default=15)\n");
fprintf (stderr," -n Reset P25 Heuristics and initState variables on mixed signal decoding\n");
fprintf (stderr," Helps when decoding mixed signal types at same time\n");
fprintf (stderr," (WiP! May Cause Slow Memory Leak - Experimental)\n");
fprintf (stderr," Helps when decoding mixed signal types (P25P1) at same time\n");
fprintf (stderr," (WiP! May Cause Slow Memory Leak or System Hang - Experimental)\n");
fprintf (stderr," -T Enable DMR TDMA Stereo Voice (Two Slot Dual Voices)\n");
fprintf (stderr," This feature will open two streams for slot 1 voice and slot 2 voice\n");
fprintf (stderr," May Cause Skipping or sync issues if bad signal/errors\n");
fprintf (stderr," -F Enable DMR TDMA Stereo Passive Frame Sync\n");
fprintf (stderr," This feature will attempt to resync less often due to excessive voice errors\n");
fprintf (stderr," Use if skipping occurs, but may cause wonky audio due to loss of good sync\n");
fprintf (stderr," -Z Log MBE Payload to console\n");
fprintf (stderr,"\n");
fprintf (stderr,"Report bugs to: https://github.com/lwvmobile/dsd-fme/issues \n");
@@ -438,15 +500,23 @@ usage ()
void
liveScanner (dsd_opts * opts, dsd_state * state)
{
//need to use this area to configure audio rates for different sources if not pulse
if (opts->audio_in_type == 1) //if stdin, switch to 8000 and single channel audio
//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; //stdin needs 8000 output, could have sworn this was working with 48000
opts->pulse_digi_rate_out = 48000; //change to 48K/1 for STDIN input
opts->pulse_digi_out_channels = 1;
if (opts->dmr_stereo == 1)
{
opts->pulse_digi_rate_out = 24000; //stdin needs 24000 by 2 channel for DMR TDMA Stereo output
opts->pulse_digi_out_channels = 2;
fprintf (stderr, "STDIN Audio Rate Out set to 24000 Khz/2 Channel \n");
}
else fprintf (stderr, "STDIN Audio Rate Out set to 48000 Khz/1 Channel \n");
opts->pulse_raw_rate_out = 48000;
opts->pulse_raw_out_channels = 1;
fprintf (stderr, "STDIN Audio Rate Out set to 8000 Khz/1 Channel \n");
}
#ifdef USE_PORTAUDIO
@@ -465,11 +535,20 @@ if (opts->audio_in_type == 1) //if stdin, switch to 8000 and single channel audi
#ifdef USE_RTLSDR
if(opts->audio_in_type == 3)
{
opts->pulse_digi_rate_out = 8000; //if rtl, switch to 8000 and 1 channel
//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?
opts->pulse_digi_rate_out = 8000; //revert to 8K/1 for RTL input, random crackling otherwise
opts->pulse_digi_out_channels = 1;
if (opts->dmr_stereo == 1)
{
opts->pulse_digi_rate_out = 24000; //rtl needs 24000 by 2 channel for DMR TDMA Stereo output
opts->pulse_digi_out_channels = 2; //minimal crackling 'may' be observed, not sure, can't test to see on DMR with RTL
fprintf (stderr, "RTL Audio Rate Out set to 24000 Khz/2 Channel \n");
}
else fprintf (stderr, "RTL Audio Rate Out set to 48000 Khz/1 Channel \n");
opts->pulse_raw_rate_out = 48000;
opts->pulse_raw_out_channels = 1;
fprintf (stderr, "RTL Audio Rate Out set to 8000 Khz/1 Channel \n");
open_rtlsdr_stream(opts);
}
#endif
@@ -669,12 +748,12 @@ main (int argc, char **argv)
initOpts (&opts);
initState (&state);
InitAllFecFunction(); //HERE
InitAllFecFunction();
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:NWrlZ")) != -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:NWrlZTF")) != -1)
{
opterr = 0;
switch (c)
@@ -771,8 +850,10 @@ main (int argc, char **argv)
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':
@@ -786,6 +867,25 @@ main (int argc, char **argv)
fprintf (stderr,"Logging MBE Payload to console\n");
break;
case 'T':
opts.dmr_stereo = 1; //just the end user option
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);
fprintf (stderr,"Experimental DMR Stereo Sync and Functionality. WIP!\n");
fprintf (stderr,"DMR Stereo will disable WAV and MBE file saving!\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,"DMR Stereo Aggressive Resync Disabled!\n");
fprintf (stderr, "%s", KNRM);
break;
case 'z':
sscanf (optarg, "%d", &opts.scoperate);
opts.errorbars = 0;
@@ -830,13 +930,17 @@ main (int argc, char **argv)
{
fprintf (stderr,"Setting audio out gain to %f\n", opts.audio_gain);
state.aout_gain = opts.audio_gain;
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," -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);
@@ -866,7 +970,7 @@ main (int argc, char **argv)
opts.frame_dmr = 1;
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
sprintf (opts.output_name, "Default Channel");
sprintf (opts.output_name, "Auto Detect");
}
else if (optarg[0] == 'd')
{
@@ -889,7 +993,7 @@ main (int argc, char **argv)
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0; //borrow from LEH
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
sprintf (opts.output_name, "X2-TDMA");
fprintf (stderr,"Decoding only X2-TDMA frames.\n");
@@ -902,7 +1006,7 @@ main (int argc, char **argv)
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0; //borrow from LEH
opts.frame_dpmr = 0;
opts.frame_provoice = 1;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
@@ -911,8 +1015,7 @@ main (int argc, char **argv)
opts.mod_gfsk = 1;
state.rf_mod = 2;
sprintf (opts.output_name, "ProVoice");
//fprintf (stderr,"Setting symbol rate to 9600 / second\n");
//fprintf (stderr,"Enabling only GFSK modulation optimizations.\n");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding only ProVoice frames.\n");
}
else if (optarg[0] == '1')
@@ -925,9 +1028,9 @@ main (int argc, char **argv)
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
opts.mod_gfsk = 0;
opts.mod_c4fm = 1;
opts.mod_qpsk = 0;
opts.mod_gfsk = 0;
state.rf_mod = 0; //
sprintf (opts.output_name, "P25P1");
fprintf (stderr,"Decoding only P25 Phase 1 frames.\n");
@@ -942,6 +1045,7 @@ main (int argc, char **argv)
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
opts.frame_ysf = 0;
state.samplesPerSymbol = 20;
state.symbolCenter = 10;
opts.mod_c4fm = 1;
@@ -951,9 +1055,30 @@ main (int argc, char **argv)
sprintf (opts.output_name, "NXDN48");
//opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate
fprintf (stderr,"Setting symbol rate to 2400 / second\n");
//fprintf (stderr,"Enabling only C4FM modulation optimizations.\n");
fprintf (stderr,"Decoding only NXDN 4800 baud frames.\n");
}
else if (optarg[0] == 'y')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 0;
opts.frame_ysf = 1;
state.samplesPerSymbol = 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] == 'n')
{
opts.frame_dstar = 0;
@@ -969,7 +1094,6 @@ main (int argc, char **argv)
opts.mod_gfsk = 0;
state.rf_mod = 0;
sprintf (opts.output_name, "NXDN96");
//fprintf (stderr,"Enabling only C4FM modulation optimizations.\n");
fprintf (stderr,"Decoding only NXDN 9600 baud frames.\n");
}
else if (optarg[0] == 'r')
@@ -986,13 +1110,8 @@ main (int argc, char **argv)
opts.mod_qpsk = 0;
opts.mod_gfsk = 0; //
state.rf_mod = 0; //
//opts.pulse_raw_rate_out = 24000; //doing tests with 2 channels at 24000 for 48000 audio default in pulse
//opts.pulse_digi_rate_out = 24000; //need to copy this to rtl type in and change rate out to 8000
//opts.pulse_raw_out_channels = 2;
//opts.pulse_digi_out_channels = 2; //2
sprintf (opts.output_name, "DMR/MOTOTRBO");
//sprintf (opts.output_name, "DMR/MOTOTRBO Left");
fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
//fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
fprintf (stderr,"Decoding only DMR/MOTOTRBO frames.\n");
}
else if (optarg[0] == 'm')
@@ -1005,6 +1124,7 @@ main (int argc, char **argv)
opts.frame_dmr = 0;
opts.frame_provoice = 0;
opts.frame_dpmr = 1;
opts.frame_ysf = 0; //testing with NXDN48 parameters
state.samplesPerSymbol = 20; //same as NXDN48 - 20
state.symbolCenter = 10; //same as NXDN48 - 10
opts.mod_c4fm = 1;
@@ -1013,11 +1133,10 @@ main (int argc, char **argv)
state.rf_mod = 0;
sprintf (opts.output_name, "dPMR");
fprintf(stderr, "Notice: dPMR cannot autodetect polarity. \n Use -xd option if Inverted Signal expected.\n");
//fprintf(stderr, "Enabling only C4FM modulation optimizations.\n");
fprintf(stderr, "Decoding only dPMR frames.\n");
}
break;
//don't mess with the modulations, doesn't really do anything anyways
//don't mess with the modulations, doesn't really do anything meaningful anyways
case 'm':
if (optarg[0] == 'a')
{
@@ -1127,7 +1246,6 @@ main (int argc, char **argv)
if (opts.use_ncurses_terminal == 1)
{
ncursesOpen();
//ncursesPrinter(&opts, &state);
}
if (opts.resume > 0)
@@ -1165,6 +1283,7 @@ main (int argc, char **argv)
{
opts.split = 1;
opts.playoffset = 0;
opts.playoffsetR = 0;
opts.delay = 0;
if (strlen(opts.wav_out_file) > 0)
{
@@ -1179,6 +1298,7 @@ main (int argc, char **argv)
{
opts.split = 1;
opts.playoffset = 0;
opts.playoffsetR = 0;
opts.delay = 0;
if (strlen(opts.wav_out_file) > 0)
{
@@ -1191,13 +1311,14 @@ main (int argc, char **argv)
openAudioInDevice (&opts);
fprintf (stderr,"Press CTRL + C twice to close.\n"); //Kindly remind user to double tap CTRL + C
fprintf (stderr,"Press CTRL + C twice to close.\n");
}
else
{
opts.split = 0;
opts.playoffset = 25; // 38
opts.playoffset = 25; // 38
opts.playoffsetR = 25; // 38
opts.delay = 0;
openAudioInDevice (&opts); //disabled all four instances of openAudio devices, in and out for now
opts.audio_out_fd = opts.audio_in_fd;
@@ -1205,7 +1326,8 @@ main (int argc, char **argv)
if (opts.playfiles == 1)
{
opts.pulse_digi_rate_out = 8000; //need set to 8000 for amb/imb playback
//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
playMbeFiles (&opts, &state, argc, argv);
@@ -1214,8 +1336,8 @@ main (int argc, char **argv)
else
{
liveScanner (&opts, &state);
}
if (opts.use_ncurses_terminal == 1){
//ncursesClose ();
}

View File

@@ -126,44 +126,78 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
else
{
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);
#ifdef AMBE_PACKET_OUT
for(i=0; i<49; i++) {
ambe_d_str[i] = ambe_d[i] + '0';
//stereo slots and slot 0 (left slot)
if (state->currentslot == 0 && opts->dmr_stereo == 1)
{
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);
}
ambe_d_str[49] = '\0';
// print binary string
fprintf (stderr, "\n?\t?\t%s\t", ambe_d_str);
// print error data
fprintf (stderr, "E1: %d; E2: %d; S: %s", state->errs, state->errs2, state->err_str);}
#endif
if (opts->mbe_out_f != NULL)
//stereo slots and slot 1 (right slot)
if (state->currentslot == 1 && opts->dmr_stereo == 1)
{
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);
//just put this in here for troubleshooting for now
if (opts->mbe_out_f != NULL)
{
saveAmbe2450Data (opts, state, ambe_d);
}
}
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);
if (opts->mbe_out_f != NULL)
{
saveAmbe2450Data (opts, state, ambe_d);
}
}
}
if (opts->errorbars == 1)
{
//state->err_buf = state->err_str; //make comy to compare, and only print when comparison differs?? THIS HERE HERE
//strncpy (state->err_buf, state->err_str, sizeof(state->err_str)); //is this the correct placement for this? want it just before err_str is set?
fprintf (stderr, "%s", state->err_str); //this the actual error 'bar' ==== printer, find way to keep this entire string from printing constantly unless err_str changes
//fprintf (stderr, "%s", state->err_str); //this the actual error 'bar' ==== printer, find way to keep this entire string from printing constantly unless err_str changes
//fprintf (stderr, "%s", state->err_buf);
}
state->debug_audio_errors += state->errs2;
processAudio (opts, state);
if (opts->wav_out_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
state->debug_audio_errorsR += state->errs2R;
if (opts->dmr_stereo == 1 && state->currentslot == 0)
{
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)
{
playSynthesizedVoiceR (opts, state);
}
}
if (opts->dmr_stereo == 0)
{
processAudio (opts, state);
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
if (opts->wav_out_f != NULL && opts->dmr_stereo == 0)
{
writeSynthesizedVoice (opts, state);
}
/*
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
*/
}
/* This function decipher data */

File diff suppressed because it is too large Load Diff

View File

@@ -96,12 +96,7 @@ resetState (dsd_state * state)
state->nxdn_last_ran = 0;
//#ifdef TRACE_DSD
// state->debug_sample_index = 0;
// state->debug_label_file = NULL;
// state->debug_label_dibit_file = NULL;
// state->debug_label_imbe_file = NULL;
//#endif
//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
initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over, mitigated with a reset flag
}

View File

@@ -94,6 +94,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
}
else if (opts->audio_in_type == 1) {
result = sf_read_short(opts->audio_in_file, &sample, 1);
//fprintf (stderr, "..");
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?
@@ -300,8 +301,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
state->lastsample = sample;
//steal sample here for rtl input or stdin input
state->input_sample_buffer = sample; //sample or sum, honestly this seemt to be best place to grab this sadly, sounds terrible most everywhere else
}
symbol = (sum / count);

View File

@@ -23,8 +23,19 @@ upsample (dsd_state * state, float invalue)
int i, j, sum;
float *outbuf1, c, d;
outbuf1 = state->audio_out_float_buf_p;
if (state->currentslot == 0 && state->dmr_stereo == 1)
{
outbuf1 = state->audio_out_float_buf_p;
}
if (state->currentslot == 1 && state->dmr_stereo == 1)
{
outbuf1 = state->audio_out_float_buf_pR;
}
if (state->dmr_stereo == 0)
{
outbuf1 = state->audio_out_float_buf_p;
}
//outbuf1 = state->audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
d = invalue;
@@ -43,6 +54,33 @@ upsample (dsd_state * state, float invalue)
*outbuf1 = d;
outbuf1++;
if (state->currentslot == 1 && state->dmr_stereo == 1)
{
if (state->audio_out_idx2R > 24)
{
// smoothing
outbuf1 -= 16;
for (j = 0; j < 4; j++)
{
for (i = 0; i < 6; i++)
{
sum = 0;
outbuf1 -= 2;
sum += (int)*outbuf1;
outbuf1 += 2;
sum += (int)*outbuf1;
outbuf1 += 2;
sum += (int)*outbuf1;
outbuf1 -= 2;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 8;
}
}
}
if (state->currentslot == 0 && state->dmr_stereo == 1)
{
if (state->audio_out_idx2 > 24)
{
// smoothing
@@ -65,4 +103,30 @@ upsample (dsd_state * state, float invalue)
outbuf1 -= 8;
}
}
}
if (state->dmr_stereo == 0)
{
if (state->audio_out_idx2 > 24)
{
// smoothing
outbuf1 -= 16;
for (j = 0; j < 4; j++)
{
for (i = 0; i < 6; i++)
{
sum = 0;
outbuf1 -= 2;
sum += (int)*outbuf1;
outbuf1 += 2;
sum += (int)*outbuf1;
outbuf1 += 2;
sum += (int)*outbuf1;
outbuf1 -= 2;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 8;
}
}
}
}

View File

@@ -39,6 +39,9 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) {
unsigned int bitbuffer = 0;
const int *w, *x;
//set carrier to 1 so ncurses will light up green
state->carrier = 1;
if (opts->errorbars == 1) {
fprintf (stderr, "e:");
}
@@ -56,7 +59,7 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) {
} else {
framecount = 1; //just saw a sync frame; there should be 20 not 21 till the next
}
//why is this running in a loop for?
while (sync_missed < 3) {
memset(ambe_fr, 0, 96);
@@ -86,6 +89,7 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) {
ambe_fr[*w][*x] = (1 & dibit);
w++;
x++;
}
@@ -128,14 +132,31 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) {
slowdata[0] ^= 0x70;
slowdata[1] ^= 0x4f;
slowdata[2] ^= 0x93;
//fprintf (stderr, "unscrambled- %s",slowdata);
//fprintf (stderr, "unscrambled- %02X %02X %02X %02X \n", slowdata[0], slowdata[1], slowdata[2], slowdata[3] );
} else if (framecount == 0) {
//fprintf (stderr, "never scrambled-%s\n",slowdata);
}
//fprintf (stderr, "never scrambled-%c\n",slowdata);
//fprintf (stderr, "never scrambled- %02X %02X %02X %02X \n", slowdata[0], slowdata[1], slowdata[2], slowdata[3] );
}
for (short int i = 0; i < 4; i++)
{
if (slowdata[i] <= 0x7E && slowdata[i] >=0x20)
{
//fprintf (stderr, "%c", slowdata[i]);
}
//else fprintf (stderr, ".");
}
//fprintf (stderr, "\n");
framecount++;
}
//since we are in a while loop, run ncursesPrinter here.
if (opts->use_ncurses_terminal == 1)
{
ncursesPrinter(opts, state);
}
} //end while loop
end: if (opts->errorbars == 1) {
fprintf (stderr, "\n");
@@ -153,7 +174,7 @@ void processDSTAR_HD(dsd_opts * opts, dsd_state * state) {
// Note: These routines contain GPLed code. Remove if you object to that.
// Due to this, they are in a separate source file.
dstar_header_decode(radioheaderbuffer);
dstar_header_decode(state, radioheaderbuffer);
//We officially have sync now, so just pass on to the above routine:

View File

@@ -19,8 +19,9 @@
#include "fcs.h"
#include "descramble.h"
#include "dstar_header.h"
#include "dsd.h"
void dstar_header_decode(int radioheaderbuffer[660]) {
void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]) {
int radioheaderbuffer2[660];
unsigned char radioheader[41];
int octetcount, bitcount, loop;
@@ -33,6 +34,7 @@ void dstar_header_decode(int radioheaderbuffer[660]) {
deinterleave(radioheaderbuffer2, radioheaderbuffer);
len = FECdecoder(radioheaderbuffer, radioheaderbuffer2);
memset(radioheader, 0, 41);
//memset(state->dstarradioheader, 0, 41);
// note we receive 330 bits, but we only use 328 of them (41 octets)
// bits 329 and 330 are unused
octetcount = 0;
@@ -48,6 +50,14 @@ void dstar_header_decode(int radioheaderbuffer[660]) {
bitcount = 0;
}
}
//state->dstarradioheader = radioheader;
for (short i = 0; i < 41; i++)
{
state->dstarradioheader[i] = radioheader[i];
}
// print header
fprintf (stderr, "\nDSTAR HEADER: ");
//fprintf (stderr, "FLAG1: %02X - FLAG2: %02X - FLAG3: %02X\n", radioheader[0],

View File

@@ -66,12 +66,19 @@ void processNXDNData (dsd_opts * opts, dsd_state * state)
//fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
if(CrcIsGood)
{
fprintf (stderr, "%s", KCYN);
fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
fprintf (stderr, "(CRC OK) ");
fprintf (stderr, "%s", KNRM);
//fprintf (stderr, "(CRC OK) ");
state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead
}
else fprintf (stderr, "(CRC ERR) ");
else
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, "(CRC ERR) ");
fprintf (stderr, "%s", KNRM);
}
/* Decode the SACCH only when all 4 voice frame

View File

@@ -732,6 +732,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
}
/* Print the "Call Type" */
fprintf (stderr, "%s", KGRN);
fprintf(stderr, "\n %s - ", NXDN_Call_Type_To_Str(CallType)); //line break and 1 space
//sprintf (state->nxdn_call_type, NXDN_Call_Type_To_Str(CallType)); //fix warning below
//warning: format not a string literal and no format arguments [-Wformat-security]
@@ -753,12 +754,16 @@ 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);
//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)
@@ -770,18 +775,15 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
state->nxdn_key = (KeyID & 0xFF);
state->nxdn_cipher_type = CipherType;
}
fprintf(stderr, "(CRC OK) ");
//fprintf(stderr, "(CRC OK) ");
}
//fprintf(stderr, " (OK) - ");
else fprintf(stderr, "(CRC ERR) ");
//fprintf(stderr, "\nVCALL = ");
//for(i = 0; i < 8; i++)
//{
// fprintf(stderr, "0x%02X, ", ConvertBitIntoBytes(&Message[i * 8], 8) & 0xFF);
//}
//fprintf(stderr, "\n");
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, "(CRC ERR) ");
fprintf (stderr, "%s", KNRM);
}
} /* End NXDN_decode_VCALL() */

View File

@@ -80,11 +80,18 @@ void processNXDNVoice (dsd_opts * opts, dsd_state * state)
//if(CrcIsGood) fprintf(stderr, " (OK) - ");
if(CrcIsGood)
{
fprintf (stderr, "%s", KCYN);
fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
fprintf (stderr, "(CRC OK) ");
fprintf (stderr, "%s", KNRM);
//fprintf (stderr, "(CRC OK) ");
state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead
}
else fprintf(stderr, "(CRC ERR) ");
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, "(CRC ERR) ");
fprintf (stderr, "%s", KNRM);
}
/* Determine the current part of superframe

View File

@@ -469,19 +469,17 @@ processHDU(dsd_opts* opts, dsd_state* state)
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
}
//if (state->errs == 0 && algidhex != 0x80)
if (1 == 1) //always print hdu alg info
//if (opts->payload == 1 && state->errs == 0)
if (1 == 1) //print on payload == 1
{
//fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi);
fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX MFID: 0x%02X \n", algidhex, kidhex, mihex1, mihex2, mihex3, state->payload_mfid);
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, "%s", KNRM);
}
if (opts->p25enc == 1 && opts->payload == 0)
{
algidhex = strtol (algid, NULL, 2);
kidhex = strtol (kid, NULL, 2);
//fprintf (stderr, "mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex);
}
if (opts->p25lc == 1)
{

View File

@@ -51,7 +51,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
if (opts->errorbars == 1)
{
fprintf (stderr, "e:");
//fprintf (stderr, "e:");
}
// IMBE 1

View File

@@ -51,7 +51,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
if (opts->errorbars == 1)
{
fprintf (stderr, "e:");
//fprintf (stderr, "e:");
}
// IMBE 1
@@ -375,18 +375,16 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
}
//if (state->errs == 0 && algidhex != 0x80)
if (1 == 1) //always print the LDU2 alg info
//if (opts->payload == 1 && state->errs == 0)
if (1 == 1) //print on payload == 1
{
//fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi);
fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3);
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, "%s", KNRM);
}
//if (opts->p25enc == 1 && opts->payload == 0)
if (opts->payload == 0)
{
algidhex = strtol (algid, NULL, 2);
kidhex = strtol (kid, NULL, 2);
//fprintf (stderr, "mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex);
}
}

View File

@@ -22,7 +22,9 @@ processTDU (dsd_opts* opts, dsd_state* state)
// Next we should find an status dibit
if (status_count != 35) {
fprintf (stderr, "%s", KRED);
fprintf (stderr, "*** SYNC ERROR\n");
fprintf (stderr, "%s", KNRM);
}
// trailing status symbol

View File

@@ -114,7 +114,9 @@ read_and_correct_dodeca_word (dsd_opts* opts, dsd_state* state, char* dodeca, in
}
else
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " IRRECOVERABLE");
fprintf (stderr, "%s", KNRM);
}
fprintf (stderr, "\n");
#endif
@@ -293,7 +295,9 @@ processTDULC (dsd_opts* opts, dsd_state* state)
// Next we should find an status dibit
if (status_count != 35) {
fprintf (stderr, "%s", KRED);
fprintf (stderr, "*** SYNC ERROR\n");
fprintf (stderr, "%s", KNRM);
}
// trailing status symbol

View File

@@ -1,8 +1,7 @@
/*
* Copyright (C) 2016 by Jonathan Naylor, G4KLX
*
* Modifications of original code to work with OP25
* Copyright (C) 2019 by Graham J. Norbury
* Heavy Modificatins of Original Code to work for DSD-FME
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,7 +13,6 @@
* GNU General Public License for more details.
*/
#include "dsd.h"
//#include "trellis.h"
#include <cstdio>
#include <cassert>
@@ -52,6 +50,23 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
unsigned char state = 0U;
//rework quickHamming to accept unsigned intergers instead and go bit by bit
int quickHamming(unsigned int butt, unsigned int farts)
{
unsigned int i = 0, count = 0, shit = 0, shart = 0;
//fprintf (stderr, "Distance Compare %X - %X \n", butt, farts );
for (i; i < 3; i++) //shift three places tops;
{
shit = (butt >> i) & 0b1;
shart = (farts >> i) & 0b1;
if (shit != shart)
{
count++;
}
}
return count;
}
bool CDMRTrellisFixCode(unsigned char* points, unsigned int failPos, unsigned char* payload)
{
@@ -101,44 +116,107 @@ void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* paylo
// convert bits to bytes
//fprintf (stderr, "\n Tribit Binary Sequence\n ");
for (short i = 0; i < 144; i++)
{
//fprintf (stderr, "%b", bits[i]);
}
for(short int i = 0; i < 18; i++)
{
payload[i] = (bits[i * 8 + 0] << 7) | (bits[i * 8 + 1] << 6) | (bits[i * 8 + 2] << 5) | (bits[i * 8 + 3] << 4) |
(bits[i * 8 + 4] << 3) | (bits[i * 8 + 5] << 2) | (bits[i * 8 + 6] << 1) | (bits[i * 8 + 7] << 0);
}
for (int i = 0; i < 144; i++)
payload[i/8] = (payload[i/8] << 1) | bits[i];
//for (int i = 0; i < 144; i++)
//payload[i/8] = (payload[i/8] << 1) | bits[i];
//DmrDataBit[j + 0] = (TrellisReturn[17-i] >> 0) & 0x01; //example
}
unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits)
{
//unsigned char state = 0U; //move outside of function to preserve state for every iteration
//let's try reversing the points to pass through the decode table instead of flipping them here,
//it may mess up the fixcode and failpos POS
state = 0U;
for (unsigned int i = 0U; i < 49U; i++) {
for (unsigned int i = 0U; i < 49U;) //total number of points to process
{
tribits[i] = 9U;
for (unsigned int j = 0U; j < 8U; j++) {
//if (points[i] == ENCODE_TABLE[state * 8U + j]) {
if (points[i] == DECODE_TABLE[state * 8U + j]) {
//if (points[48-i] == DECODE_TABLE[state * 8U + j]) {
for (unsigned int j = 0U; j < 8U; j++)
{
//if (points[i] == DECODE_TABLE[state * 8U + j])
//if (points[48-i] == DECODE_TABLE[state * 8U + j])
if (points[i] == ENCODE_TABLE[state * 8U + j])
{
tribits[i] = j;
state = tribits[i]; //carry over if found right away
i++; //increment i by one value
break;
}
}
//try to find shortest distance for surviving paths and decide on one
//seems to be that two paths will have distance value 1, and two will have distance value 2
//need to keep totaling up a few rounds before we can eliminate a path and resume?
if (tribits[i] == 9U)
return i;
{
int distance = 0;
int maxdistance = 99; //random metric for two position distance
int pathdistance = 0;
unsigned int match = 0;
unsigned int nextmatch = 0;
unsigned int q = 0;
//only 4 possible states for each point, but in 8 (0-7) FSM states
char path[99][99] = {0}; //[i][pathcount] = distance
int pathcount = 0;
for (unsigned int o = 0; o < 64; o++) //check entire state transition table for matches
{
if (points[i] == ENCODE_TABLE[o]) //ENCODE TABLE
{
match = o / (unsigned int)8; //get dividend no remainder/decimal I hope, get fsm state 0-7
//fprintf (stderr, "\n Point #%d [%d] Match State %d Position %d Tribit Value %d \n", i, points[i], match, o, o % (unsigned int)8);
distance = quickHamming(match, state);
//fprintf (stderr, "Raw Distance Current %d\n", distance);
path[i][pathcount] = distance ; //save which table values (paths) match as possible values and distance
for (q; q < 64; q++) //check entire state transition table for next point match
{
if (points[i+1] == ENCODE_TABLE[q]) //ENCODE TABLE
{
nextmatch = q / (unsigned int)8;
path[i+1][pathcount] = quickHamming(nextmatch, q % (unsigned int)8);
//fprintf (stderr, "Raw Distance Next %d\n", path[i+1][pathcount]);
pathcount++;
//fprintf (stderr, "State 0 Match %d Distance %d \n", o, distance);
}
}
for (short int z = 0; z <= pathcount; z++) //add metrics on paths to find shortest distance
{
pathdistance = path[i][0] + path[i+1][z];
//fprintf (stderr, "Total Path Distance %d\n", pathdistance);
if (pathdistance <= maxdistance) //equal too in case of tie?
{
maxdistance = pathdistance;
tribits[i] = o % (unsigned int)8; //remainder value will be tribit value on table
if (i < 49) //just in case we are on 49 already, don't want to crash or something.
{
tribits[i+1] = q % (unsigned int)8; //remainder value will be tribit value on table
}
state = tribits[i];
//fprintf (stderr, "Point #%d [%d] - Tribit Candidate %d\n", i, points[i], tribits[i] );
//fprintf (stderr, "Point #%d [%d]- Tribit Candidate %d\n", i+1, points[i+1], tribits[i+1] );
}
}
}
//fprintf (stderr, "Selected Point #%d [%d] - Tribit Selection %d\n", i, points[i], tribits[i] );
//fprintf (stderr, "Selected Point #%d [%d]- Tribit Selection %d\n", i+1, points[i+1], tribits[i+1] );
}
state = tribits[i+1]; //not quite sure if this will be needed or not, if so, set state to last found value
i += 2; //increment i by two since we already got the next tribit value as well;
//state = tribits[i]; //not quite sure if this will be needed or not, if so, set state to last found value
//i++; //increment i by two since we already got the next tribit value as well;
}
}
//if (tribits[48U] != 0U)
if (tribits[48U] != 0U) //
{
return 48U;
}
return 999U;
}
@@ -146,7 +224,8 @@ void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits)
{
int n;
signed char dibit;
//can only assume this is giving the correct dibits out, and not inverse or something.
/*
for (int i = 0; i < 98; i++) {
n = i * 2;
if (n >= 98) n += 68;
@@ -157,19 +236,44 @@ void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits)
bool b2 = data[n] != 0x0;
if (!b1 && b2)
dibit = +3;
dibit = +3; // 1 - 01
else if (!b1 && !b2)
dibit = +1;
dibit = +1; // 0 - 00
else if (b1 && !b2)
dibit = -1;
dibit = -1; // 2 - 10
else
dibit = -3;
dibit = -3; // 3 - 11
n = INTERLEAVE_TABLE[i]; //should this go in reverse?
dibits[n] = dibit;
*/
//Keep it simple!
for (int i = 0; i < 98; i++)
{
n = INTERLEAVE_TABLE[97-i];
//n = i;
if (data[i] == 0)
{
dibits[n] = 1; //1
}
if (data[i] == 1)
{
dibits[n] = 3; //3
}
if (data[i] == 2)
{
dibits[n] = -1; //-1
}
if (data[i] == 3)
{
dibits[n] = -3; //-3
}
}
//n = INTERLEAVE_TABLE[i]; //should this go in reverse?
//n = INTERLEAVE_TABLE[97-i]; //should this go in reverse?
//dibits[n] = dibit; //should this go in reverse too? not sure on this one, but definitely the INTERLEAVE_TABLE
//n = INTERLEAVE_TABLE[97-i]; //should this go in reverse?
//dibits[97-n] = dibit;
}
//}
}
void CDMRTrellisDibitsToPoints(const signed char* dibits, unsigned char* points)
@@ -324,7 +428,7 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
}
signed char dibits[98U];
CDMRTrellisDeinterleave(data, dibits);
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\n Trellis Deinterleaved Dibits inside Decoder (converted to signed)\n ");
for (short i = 0; i < 98; i++)
@@ -333,8 +437,19 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
}
}
unsigned char points[49U];
unsigned char reverse_points[49U];
CDMRTrellisDibitsToPoints(dibits, points);
if (1 == 1)
//maybe keep point 49 at 49, since its the flush?
//fprintf (stderr, "\n Trellis Reverse Points inside Decoder\n ");
for (short i = 0; i < 49; i++)
{
reverse_points[i] = points[48-i];
//fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]);
}
//reverse_points[48] = points[48];
//fprintf (stderr, "#%d [%02u] ", 48, reverse_points[48]);
if (1 == 2)
{
fprintf (stderr, "\n Trellis Points inside Decoder\n ");
for (short i = 0; i < 49; i++)
@@ -343,19 +458,11 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
}
}
// Check the original code
unsigned char reverse_points[49U];
fprintf (stderr, "\n Trellis Reversed Points inside Decoder\n ");
for (short i = 0; i < 49; i++)
{
reverse_points[i] = points[48-i];
fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]);
}
//unsigned int failPos = CDMRTrellisCheckCode(points, tribits);
unsigned int failPos = CDMRTrellisCheckCode(reverse_points, tribits);
unsigned int failPos = CDMRTrellisCheckCode(points, tribits);
//unsigned int failPos = CDMRTrellisCheckCode(reverse_points, tribits); //stack smashing detected terminated
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\n Check Code Trellis Tribits inside Decoder\n ");
for (short i = 0; i < 49; i++)
@@ -367,27 +474,36 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
if (failPos == 999U)
{
CDMRTrellisTribitsToBits(tribits, payload);
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 999U\n ");
for (short i = 0; i < 18; i++)
fprintf (stderr, "\nTrellis Payload Tribits\n %s ", KCYN);
for (short i = 0; i < 49; i++)
{
fprintf (stderr, "#%d [%0u] ", i, tribits[i]); //shouldn't have any values greater that 0x7?
}
}
if (1 == 2)
{
fprintf (stderr, "\nTrellis Payload Tribits to Bytes inside Decoder\n %s ", KCYN);
for (short i = 0; i < 18; i++)
{
fprintf (stderr, "[%02X]", payload[i]);
}
fprintf (stderr,"%s", KNRM); //change back to normal
}
return true;
}
unsigned char savePoints[49U];
for (unsigned int i = 0U; i < 49U; i++)
//savePoints[i] = points[i];
savePoints[i] = reverse_points[i];
savePoints[i] = points[i];
//savePoints[i] = reverse_points[i];
//bool ret = CDMRTrellisFixCode(points, failPos, payload);
bool ret = CDMRTrellisFixCode(reverse_points, failPos, payload);
bool ret = CDMRTrellisFixCode(points, failPos, payload);
//bool ret = CDMRTrellisFixCode(reverse_points, failPos, payload);
if (ret){
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\n if return Trellis Tribits inside Decoder\n ");
for (short i = 0; i < 49; i++)
@@ -396,7 +512,7 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
}
}
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\nTrellis Payload Tribits to Bits fix return true\n "); //this one seems to be happening
for (short i = 0; i < 18; i++)
@@ -408,9 +524,9 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
if (failPos == 0U)
{
if (1 == 1)
if (1 == 2)
{
fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 0U\n ");
fprintf (stderr, "\nTrellis Payload Tribits to Bytes failPos == 0U\n ");
for (short i = 0; i < 18; i++)
{
fprintf (stderr, "[%02X]", payload[i]);

287
src/ysf.c Normal file
View File

@@ -0,0 +1,287 @@
/*-------------------------------------------------------------------------------
* ysf.c
* Yaesu Fusion Decoder for DSD
*
* LWVMOBILE
* 2022-04 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"
const int fichInterleave[100] = {
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96,
2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97,
3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, 78, 83, 88, 93, 98,
4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69, 74, 79, 84, 89, 94, 99,
};
const int vd2Interleave[104] = {
0, 26, 52, 78,
1, 27, 53, 79,
2, 28, 54, 80,
3, 29, 55, 81,
4, 30, 56, 82,
5, 31, 57, 83,
6, 32, 58, 84,
7, 33, 59, 85,
8, 34, 60, 86,
9, 35, 61, 87,
10, 36, 62, 88,
11, 37, 63, 89,
12, 38, 64, 90,
13, 39, 65, 91,
14, 40, 66, 92,
15, 41, 67, 93,
16, 42, 68, 94,
17, 43, 69, 95,
18, 44, 70, 96,
19, 45, 71, 97,
20, 46, 72, 98,
21, 47, 73, 99,
22, 48, 74, 100,
23, 49, 75, 101,
24, 50, 76, 102,
25, 51, 77, 103
};
const int vfrInterleave[144] = { //IMBE 7200x4400 full rate interleave schedule
0, 24, 48, 72, 96, 120, 25, 1, 73, 49, 121, 97,
2, 26, 50, 74, 98, 122, 27, 3, 75, 51, 123, 99,
4, 28, 52, 76, 100, 124, 29, 5, 77, 53, 125, 101,
6, 30, 54, 78, 102, 126, 31, 7, 79, 55, 127, 103,
8, 32, 56, 80, 104, 128, 33, 9, 81, 57, 129, 105,
10, 34, 58, 82, 106, 130, 35, 11, 83, 59, 131, 107,
12, 36, 60, 84, 108, 132, 37, 13, 85, 61, 133, 109,
14, 38, 62, 86, 110, 134, 39, 15, 87, 63, 135, 111,
16, 40, 64, 88, 112, 136, 41, 17, 89, 65, 137, 113,
18, 42, 66, 90, 114, 138, 43, 19, 91, 67, 139, 115,
20, 44, 68, 92, 116, 140, 45, 21, 93, 69, 141, 117,
22, 46, 70, 94, 118, 142, 47, 23, 95, 71, 143, 119
};
//half-rate ambe3600x2450 interleave schedule
const int YSFrW[36] = {
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 2,
0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2
};
// bit index
const int YSFrX[36] = {
23, 10, 22, 9, 21, 8,
20, 7, 19, 6, 18, 5,
17, 4, 16, 3, 15, 2,
14, 1, 13, 0, 12, 10,
11, 9, 10, 8, 9, 7,
8, 6, 7, 5, 6, 4
};
// bit 0
// frame index
const int YSFrY[36] = {
0, 2, 0, 2, 0, 2,
0, 2, 0, 3, 0, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3
};
// bit index
const int YSFrZ[36] = {
5, 3, 4, 2, 3, 1,
2, 0, 1, 13, 0, 12,
22, 11, 21, 10, 20, 9,
19, 8, 18, 7, 17, 6,
16, 5, 15, 4, 14, 3,
13, 2, 12, 1, 11, 0
};
void processYSF(dsd_opts * opts, dsd_state * state) //YSF
{
//480 dibits - 20 dibit sync leaves 460 dibits (920 bits) each 'superframe'
fprintf (stderr, "processYSF Function \n");
uint32_t i, j, k;
unsigned char dibit;
const int *w, *x, *y, *z;
char ambe_fr[8][4][24];
unsigned char storage[8][4][24]; //may expand later
unsigned char discard[460]; //just set up for now to hold random dibit grabs with nothing to do but skip them
unsigned char vch[4][36]; //correct size array for 4*32 dibit VD2 VCH?
unsigned char fich[200]; //store as bits after deinterleaving
unsigned char fichraw[100];
unsigned char fichdibits[100]; //deinterleaved fich dibits
unsigned char fichbytes[26];
unsigned int fi = 0;
unsigned int cs = 0;
unsigned int cm = 0;
unsigned int bn = 0;
unsigned int bt = 0;
unsigned int fn = 0;
unsigned int ft = 0;
unsigned int mr = 0;
unsigned int ip = 0;
unsigned int dt = 0; //DT, 2 bytes (according to manual, but has to be two bits)
unsigned int sq = 0;
unsigned int sc = 0;
int vd1 = 1;
int vd2 = 0;
unsigned int msbI = 0;
unsigned int lsbI = 0;
unsigned char vd2BitsRaw[104];
opts->inverted_ysf = 0; //here for testing purposes, move to main later
for (i = 0; i < 100; i++) //100 dibits for fich
{
dibit = getDibit (opts, state);
if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1
{
dibit = (dibit ^ 2);
}
fichraw[i] = dibit; //raw storage for debug
fichdibits[fichInterleave[i]] = dibit; //sort into proper order
//fich[i*2] = (1 & (dibit >> 1)); // bit 1
//fich[i*2+1] = (1 & dibit); // bit 0
fich[i*2] = (fichdibits[fichInterleave[i]] >> 1) & 1;
//fprintf (stderr, "%b", fich[i*2]);
fich[i*2+1] = fichdibits[fichInterleave[i]] & 1;
//fprintf (stderr, "%b", fich[i*2+1]);
if (i == 4)
{
//datatype = dibit;
}
}
//fprintf (stderr, "\nFICH BYTES = ");
for (i = 0; i < 25; i++) //bits to bytes
{
fichbytes[i] = 0; //initialize to see what isn't beign set
fichbytes[i] = ( (fich[i*8] << 7) | (fich[i*8+1] << 6) | (fich[i*8+2] << 5) | (fich[i*8+3] << 4) |
(fich[i*8+4] << 3) | (fich[i*8+5] << 2) | (fich[i*8+6] << 1) | (fich[i*8+7] << 0) );
//fprintf (stderr, "[%02X]", fichbytes[i]);
}
//fprintf (stderr, "\n");
//datatype = (fich[8] << 1) + fich[9];
dt = fichbytes[2] & 0x03;
for (i = 0; i < 2; i++)
{
//datatype << 1;
//datatype = datatype | fichraw[i+8];
//fprintf (stderr, "%02b", fichdibits[i+4]);
//fprintf (stderr, "%02b", fichdibits[i+11]);
}
//fprintf (stderr, "Datatype = %02b\n", dt);
//quick dirty VD1 method?
if (0 == 0) //dt == 0 for VD1
{
fprintf (stderr, "processYSF VD1 \n");
for (j = 0; j < 5; j++) //5 DCH and VCH
{
w = YSFrW;
x = YSFrX;
y = YSFrY;
z = YSFrZ;
k = 0;
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1
{
dibit = (dibit ^ 2);
}
storage[j][*w][*x] = (1 & (dibit >> 1)); // bit 1
storage[j][*y][*z] = (1 & dibit); // bit 0
}
//AMBE VCH
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1
{
dibit = (dibit ^ 2);
}
ambe_fr[j][*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[j][*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
//processMbeFrame (opts, state, NULL, ambe_fr[j], NULL);
} //end j < 4 loop
} //end VD1
//move processMbeFrame to outside of dibit loop to prevent slip
for (j = 0; j < 5; j++)
{
//processMbeFrame (opts, state, NULL, ambe_fr[j], NULL);
}
//VD2 method
if (0 == 3) //dt == 3
{
fprintf (stderr, "processYSF VD2 \n");
for (j = 0; j < 4; j++)
{
//VCH[j] and VeCH[j]
for (i = 0; i < 20; i++) //32?
{
dibit = getDibit (opts, state);
if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1
{
dibit = (dibit ^ 2);
}
//collect dibits into array for processing
vch[j][i] = dibit;
w = YSFrW;
x = YSFrX;
y = YSFrY;
z = YSFrZ;
msbI = vd2Interleave[(j+1)*i]; //don't this this is remotely correct, really could use the manual right about now
lsbI = vd2Interleave[(j+1)*i+1];
vd2BitsRaw[msbI] = ((vch[j][i] >> 1) & 1);
vd2BitsRaw[lsbI] = (vch[j][i] & 1);
} // VCH[j]
//DCH[j]
for (i = 0; i < 20; i++) //32?
{
dibit = getDibit (opts, state);
if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1
{
dibit = (dibit ^ 2);
}
discard[i] = dibit;
} //end DCH[j]
} //end for j loop
} //end VD2
} //end processYSF