mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 17:27:21 -05:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef07b48540 | ||
|
|
db67a8b227 | ||
|
|
4e2c4577d5 | ||
|
|
e581c96560 | ||
|
|
f3505269d0 | ||
|
|
20ccdbbced | ||
|
|
fc2fb99502 | ||
|
|
143c560958 | ||
|
|
d122d7e935 | ||
|
|
d0f9bb4bad | ||
|
|
ac752029bd | ||
|
|
5b994f5129 | ||
|
|
ec7d7c24a5 | ||
|
|
1d49481f2d | ||
|
|
7ca8cb421c | ||
|
|
4eb44b3c67 | ||
|
|
e16e4b61fc | ||
|
|
fbd04fa869 | ||
|
|
7f9b852f36 | ||
|
|
f5a7ab2b77 | ||
|
|
ffe6098fb8 | ||
|
|
157ca8c043 | ||
|
|
b722e43a3a |
@@ -1,7 +1,3 @@
|
|||||||
## Notice
|
|
||||||
|
|
||||||
These examples will need to be modified to run on the 'lite' branch, or any precompiled Windows binaries released. (i.e. dsd-fme to dsd-fme-lite.exe, -i pulse -o pulse, etc)
|
|
||||||
|
|
||||||
### Example Usage and Notes!
|
### Example Usage and Notes!
|
||||||
|
|
||||||
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25 (1 and 2) . To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed.
|
`dsd-fme` is all you need to run for pulse input, pulse output, and auto detect for DMR BS/MS, and P25 (1 and 2) . To use other decoding methods which cannot be auto detected, please use the following command line switches. Make sure to route audio into and out of DSD-FME using pavucontrol and virtual sinks as needed.
|
||||||
@@ -125,7 +121,7 @@ For Connect Plus, enumerate your list from 1 to the last channel and add the fre
|
|||||||
|
|
||||||
Currently uncoded/unknown DMR trunking systems include Hytera XPT.
|
Currently uncoded/unknown DMR trunking systems include Hytera XPT.
|
||||||
|
|
||||||
Trunking Note4: NXDN Trunking may also require a channel map file, depending on the system. If it uses a custom range (above 800), then channels will need to be mapped. If channels do not require mapping (have channels below 800) but you are not tuning properly, then please use a channel_map and please report the issue in the issues along with the channels you are tuning and the actual rf frequency so corrections can be made.
|
Trunking Note4: NXDN TRunking will require a channel map. Please see the example folder for an appropriate channel map. ~NXDN Trunking may also require a channel map file, depending on the system. If it uses a custom range (above 800), then channels will need to be mapped. If channels do not require mapping (have channels below 800) but you are not tuning properly, then please use a channel_map and please report the issue in the issues along with the channels you are tuning and the actual rf frequency so corrections can be made.~
|
||||||
|
|
||||||
Channel Map and Group CSV Note: Leave the top line of the channel_map.csv and group.csv as the label, do not delete the line, if no line is there, dsd_import skips the first line so it will not import the first channel or first group in those files if there is something there that isn't a label.
|
Channel Map and Group CSV Note: Leave the top line of the channel_map.csv and group.csv as the label, do not delete the line, if no line is there, dsd_import skips the first line so it will not import the first channel or first group in those files if there is something there that isn't a label.
|
||||||
|
|
||||||
|
|||||||
8
examples/nxdn_chan_map.csv
Normal file
8
examples/nxdn_chan_map.csv
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
channel(dec), freq(Hz)
|
||||||
|
141,423862500
|
||||||
|
142,424337500
|
||||||
|
143,424912500
|
||||||
|
203,424100000
|
||||||
|
204,424625000
|
||||||
|
271,422650000
|
||||||
|
302,423287500
|
||||||
|
5
examples/nxdn_sc_key.csv
Normal file
5
examples/nxdn_sc_key.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
key(dec), value(dec), load any single keys as key 0
|
||||||
|
0,23466
|
||||||
|
1,12345
|
||||||
|
2,32700
|
||||||
|
63,32767
|
||||||
|
@@ -203,8 +203,10 @@ typedef struct
|
|||||||
int playoffsetR;
|
int playoffsetR;
|
||||||
char mbe_out_dir[1024];
|
char mbe_out_dir[1024];
|
||||||
char mbe_out_file[1024];
|
char mbe_out_file[1024];
|
||||||
|
char mbe_out_fileR[1024]; //second slot on a TDMA system
|
||||||
char mbe_out_path[2048]; //1024
|
char mbe_out_path[2048]; //1024
|
||||||
FILE *mbe_out_f;
|
FILE *mbe_out_f;
|
||||||
|
FILE *mbe_out_fR; //second slot on a TDMA system
|
||||||
FILE *symbol_out_f;
|
FILE *symbol_out_f;
|
||||||
float audio_gain;
|
float audio_gain;
|
||||||
float audio_gainR;
|
float audio_gainR;
|
||||||
@@ -218,6 +220,7 @@ typedef struct
|
|||||||
char szNumbers[1024]; //**tera 10/32/64 char str
|
char szNumbers[1024]; //**tera 10/32/64 char str
|
||||||
short int symbol_out;
|
short int symbol_out;
|
||||||
short int mbe_out; //flag for mbe out, don't attempt fclose more than once
|
short int mbe_out; //flag for mbe out, don't attempt fclose more than once
|
||||||
|
short int mbe_outR; //flag for mbe out, don't attempt fclose more than once
|
||||||
SNDFILE *wav_out_f;
|
SNDFILE *wav_out_f;
|
||||||
SNDFILE *wav_out_fR;
|
SNDFILE *wav_out_fR;
|
||||||
SNDFILE *wav_out_raw;
|
SNDFILE *wav_out_raw;
|
||||||
@@ -327,7 +330,8 @@ typedef struct
|
|||||||
//csv import filenames
|
//csv import filenames
|
||||||
char group_in_file[1024];
|
char group_in_file[1024];
|
||||||
char lcn_in_file[1024];
|
char lcn_in_file[1024];
|
||||||
char chan_in_file[1024];
|
char chan_in_file[1024];
|
||||||
|
char key_in_file[1024];
|
||||||
//end import filenames
|
//end import filenames
|
||||||
|
|
||||||
//reverse mute
|
//reverse mute
|
||||||
@@ -355,6 +359,10 @@ typedef struct
|
|||||||
//OSS audio - slot preference
|
//OSS audio - slot preference
|
||||||
uint8_t slot_preference;
|
uint8_t slot_preference;
|
||||||
|
|
||||||
|
//'DSP' Format Output
|
||||||
|
uint8_t use_dsp_output;
|
||||||
|
char dsp_out_file[2048];
|
||||||
|
|
||||||
} dsd_opts;
|
} dsd_opts;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -508,9 +516,11 @@ typedef struct
|
|||||||
|
|
||||||
unsigned int dmr_fid;
|
unsigned int dmr_fid;
|
||||||
unsigned int dmr_so;
|
unsigned int dmr_so;
|
||||||
|
unsigned int dmr_flco;
|
||||||
|
|
||||||
unsigned int dmr_fidR;
|
unsigned int dmr_fidR;
|
||||||
unsigned int dmr_soR;
|
unsigned int dmr_soR;
|
||||||
|
unsigned int dmr_flcoR;
|
||||||
|
|
||||||
char slot1light[8];
|
char slot1light[8];
|
||||||
char slot2light[8];
|
char slot2light[8];
|
||||||
@@ -527,8 +537,9 @@ typedef struct
|
|||||||
//new stuff below here
|
//new stuff below here
|
||||||
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
|
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
|
||||||
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
|
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
|
||||||
|
uint8_t cap_plus_csbk_bits[12*8*4]; //CSBK Cap+ FL initial and appended block bit storage
|
||||||
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
|
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
|
||||||
char dmr_embedded_signalling[2][6][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)
|
char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)
|
||||||
|
|
||||||
char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify
|
char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify
|
||||||
int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet.
|
int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet.
|
||||||
@@ -545,8 +556,9 @@ typedef struct
|
|||||||
|
|
||||||
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
|
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
|
||||||
|
|
||||||
unsigned char * dpmr_caller_id;
|
char dpmr_caller_id[20];
|
||||||
unsigned char * dpmr_target_id;
|
char dpmr_target_id[20];
|
||||||
|
|
||||||
int dpmr_color_code;
|
int dpmr_color_code;
|
||||||
|
|
||||||
short int dmr_stereo; //need state variable for upsample function
|
short int dmr_stereo; //need state variable for upsample function
|
||||||
@@ -571,6 +583,8 @@ typedef struct
|
|||||||
unsigned long long int p2_wacn;
|
unsigned long long int p2_wacn;
|
||||||
unsigned long long int p2_sysid;
|
unsigned long long int p2_sysid;
|
||||||
unsigned long long int p2_cc; //p1 NAC
|
unsigned long long int p2_cc; //p1 NAC
|
||||||
|
unsigned long long int p2_siteid;
|
||||||
|
unsigned long long int p2_rfssid;
|
||||||
int p2_hardset; //flag for checking whether or not P2 wacn and sysid are hard set by user
|
int p2_hardset; //flag for checking whether or not P2 wacn and sysid are hard set by user
|
||||||
int p2_scramble_offset; //offset counter for scrambling application
|
int p2_scramble_offset; //offset counter for scrambling application
|
||||||
int p2_vch_chan_num; //vch channel number (0 or 1, not the 0-11 TS)
|
int p2_vch_chan_num; //vch channel number (0 or 1, not the 0-11 TS)
|
||||||
@@ -640,12 +654,15 @@ typedef struct
|
|||||||
uint32_t nxdn_location_sys_code;
|
uint32_t nxdn_location_sys_code;
|
||||||
uint16_t nxdn_location_site_code;
|
uint16_t nxdn_location_site_code;
|
||||||
|
|
||||||
|
//multi-key array for nxdn keys
|
||||||
|
unsigned long long int rkey_array[0x1FF];
|
||||||
|
|
||||||
//dmr late entry mi
|
//dmr late entry mi
|
||||||
uint64_t late_entry_mi_fragment[2][7][3];
|
uint64_t late_entry_mi_fragment[2][7][3];
|
||||||
|
|
||||||
//dmr manufacturer branding and sub_branding (i.e., Motorola and Con+)
|
//dmr manufacturer branding and sub_branding (i.e., Motorola and Con+)
|
||||||
char dmr_branding[99];
|
char dmr_branding[20];
|
||||||
char dmr_branding_sub[99];
|
char dmr_branding_sub[80];
|
||||||
|
|
||||||
//Remus DMR End Call Alert Beep
|
//Remus DMR End Call Alert Beep
|
||||||
int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag
|
int dmr_end_alert[2]; //dmr TLC end call alert beep has already played once flag
|
||||||
@@ -749,13 +766,16 @@ int get_dibit_and_analog_signal (dsd_opts * opts, dsd_state * state, int * out_a
|
|||||||
void skipDibit (dsd_opts * opts, dsd_state * state, int count);
|
void skipDibit (dsd_opts * opts, dsd_state * state, int count);
|
||||||
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
||||||
void saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
void saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
||||||
|
void saveAmbe2450DataR (dsd_opts * opts, dsd_state * state, char *ambe_d); //tdma slot 2
|
||||||
void PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
void PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
||||||
void PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
void PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
||||||
int readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
int readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
||||||
int readAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
int readAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
|
||||||
void openMbeInFile (dsd_opts * opts, dsd_state * state);
|
void openMbeInFile (dsd_opts * opts, dsd_state * state);
|
||||||
void closeMbeOutFile (dsd_opts * opts, dsd_state * state);
|
void closeMbeOutFile (dsd_opts * opts, dsd_state * state);
|
||||||
|
void closeMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
|
||||||
void openMbeOutFile (dsd_opts * opts, dsd_state * state);
|
void openMbeOutFile (dsd_opts * opts, dsd_state * state);
|
||||||
|
void openMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
|
||||||
void openWavOutFile (dsd_opts * opts, dsd_state * state);
|
void openWavOutFile (dsd_opts * opts, dsd_state * state);
|
||||||
void openWavOutFileL (dsd_opts * opts, dsd_state * state);
|
void openWavOutFileL (dsd_opts * opts, dsd_state * state);
|
||||||
void openWavOutFileR (dsd_opts * opts, dsd_state * state);
|
void openWavOutFileR (dsd_opts * opts, dsd_state * state);
|
||||||
@@ -868,7 +888,7 @@ int32_t GetdPmrColorCode(uint8_t ChannelCodeBit[24]);
|
|||||||
void BPTCDeInterleaveDMRData(uint8_t * Input, uint8_t * Output);
|
void BPTCDeInterleaveDMRData(uint8_t * Input, uint8_t * Output);
|
||||||
uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DMRDataExtracted[96], uint8_t R[3]);
|
uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DMRDataExtracted[96], uint8_t R[3]);
|
||||||
uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDataExtracted[77]);
|
uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDataExtracted[77]);
|
||||||
uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32]);
|
uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32], uint32_t ParityCheckTypeOdd);
|
||||||
|
|
||||||
//Reed Solomon (12,9) functions
|
//Reed Solomon (12,9) functions
|
||||||
void rs_12_9_calc_syndrome(rs_12_9_codeword_t *codeword, rs_12_9_poly_t *syndrome);
|
void rs_12_9_calc_syndrome(rs_12_9_codeword_t *codeword, rs_12_9_poly_t *syndrome);
|
||||||
@@ -881,6 +901,8 @@ uint16_t ComputeCrcCCITT(uint8_t * DMRData);
|
|||||||
uint16_t ComputeCrcCCITT16d(const uint8_t buf[], uint8_t len);
|
uint16_t ComputeCrcCCITT16d(const uint8_t buf[], uint8_t len);
|
||||||
uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes, uint32_t * CRCComputed, uint32_t CRCMask);
|
uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes, uint32_t * CRCComputed, uint32_t CRCMask);
|
||||||
uint8_t ComputeCrc5Bit(uint8_t * DMRData);
|
uint8_t ComputeCrc5Bit(uint8_t * DMRData);
|
||||||
|
uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData);
|
||||||
|
uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData);
|
||||||
|
|
||||||
//new simplified dmr functions
|
//new simplified dmr functions
|
||||||
void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst);
|
void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst);
|
||||||
@@ -916,10 +938,14 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state);
|
|||||||
void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc, char ambe_fr[4][24], char ambe_fr2[4][24], char ambe_fr3[4][24]);
|
void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc, char ambe_fr[4][24], char ambe_fr2[4][24], char ambe_fr3[4][24]);
|
||||||
void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state);
|
void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state);
|
||||||
|
|
||||||
|
//handle Single Burst (Voice Burst F) or Reverse Channel Signalling
|
||||||
|
void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power);
|
||||||
|
|
||||||
//DMR FEC/CRC from Boatbod - OP25
|
//DMR FEC/CRC from Boatbod - OP25
|
||||||
bool Hamming17123(uint8_t* d);
|
bool Hamming17123(uint8_t* d);
|
||||||
uint8_t crc8(uint8_t bits[], unsigned int len);
|
uint8_t crc8(uint8_t bits[], unsigned int len);
|
||||||
bool crc8_ok(uint8_t bits[], unsigned int len);
|
bool crc8_ok(uint8_t bits[], unsigned int len);
|
||||||
|
uint8_t crc7(uint8_t bits[], unsigned int len);
|
||||||
|
|
||||||
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
||||||
void LFSR(dsd_state * state);
|
void LFSR(dsd_state * state);
|
||||||
@@ -1008,6 +1034,7 @@ unsigned long long int edacs_bch (unsigned long long int message);
|
|||||||
int csvGroupImport(dsd_opts * opts, dsd_state * state);
|
int csvGroupImport(dsd_opts * opts, dsd_state * state);
|
||||||
int csvLCNImport(dsd_opts * opts, dsd_state * state);
|
int csvLCNImport(dsd_opts * opts, dsd_state * state);
|
||||||
int csvChanImport(dsd_opts * opts, dsd_state * state);
|
int csvChanImport(dsd_opts * opts, dsd_state * state);
|
||||||
|
int csvKeyImport(dsd_opts * opts, dsd_state * state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -1033,7 +1060,7 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload);
|
|||||||
int ez_rs28_ess (int payload[96], int parity[168]); //ezpwd bridge for FME
|
int ez_rs28_ess (int payload[96], int parity[168]); //ezpwd bridge for FME
|
||||||
int ez_rs28_facch (int payload[156], int parity[114]); //ezpwd bridge for FME
|
int ez_rs28_facch (int payload[156], int parity[114]); //ezpwd bridge for FME
|
||||||
int ez_rs28_sacch (int payload[180], int parity[132]); //ezpwd bridge for FME
|
int ez_rs28_sacch (int payload[180], int parity[132]); //ezpwd bridge for FME
|
||||||
unsigned long long int isch_lookup (unsigned long long int isch); //isch map lookup
|
int isch_lookup (unsigned long long int isch); //isch map lookup
|
||||||
int bd_bridge (int payload[196], uint8_t decoded[12]); //bridge to Michael Ossmann Block De-interleaver and 1/2 rate trellis decoder
|
int bd_bridge (int payload[196], uint8_t decoded[12]); //bridge to Michael Ossmann Block De-interleaver and 1/2 rate trellis decoder
|
||||||
int crc16_lb_bridge (int payload[190], int len);
|
int crc16_lb_bridge (int payload[190], int len);
|
||||||
int crc12_xb_bridge (int payload[190], int len);
|
int crc12_xb_bridge (int payload[190], int len);
|
||||||
|
|||||||
62
src/bptc.c
62
src/bptc.c
@@ -134,6 +134,13 @@ const uint8_t DeInterleaveReverseChannelBptc[32] =
|
|||||||
24, 9, 26, 11, 28, 13, 30, 15
|
24, 9, 26, 11, 28, 13, 30, 15
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t DeInterleaveReverseChannelBptcPlacement[32] =
|
||||||
|
{
|
||||||
|
0, 16, 1, 17, 2, 18, 3, 19,
|
||||||
|
4, 20, 5, 21, 6, 22, 7, 23,
|
||||||
|
8, 24, 9, 25, 10, 26, 11, 27,
|
||||||
|
12, 28, 13, 29, 14, 30, 15, 31
|
||||||
|
};
|
||||||
|
|
||||||
/* Functions ----------------------------------------------------------------*/
|
/* Functions ----------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -192,18 +199,10 @@ uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* R(0) to R(2) may be used to transport some
|
|
||||||
* Restricted Access System (RAS) information,
|
|
||||||
* So save these three bytes before reset all of them
|
|
||||||
* See patent US 2013/0288643 A1 */
|
|
||||||
R[0] = DataMatrix[0][2]; /* Save R(0) */
|
|
||||||
R[1] = DataMatrix[0][1]; /* Save R(1) */
|
|
||||||
R[2] = DataMatrix[0][0]; /* Save R(2) */
|
|
||||||
|
|
||||||
/* Set to 0 R(0) to R(2) - See DMR standard chapter B1.1 BPTC (196,96) */
|
/* Set to 0 R(0) to R(2) - See DMR standard chapter B1.1 BPTC (196,96) */
|
||||||
DataMatrix[0][0] = 0; /* R(2) */
|
// DataMatrix[0][0] = 0; /* R(2) */
|
||||||
DataMatrix[0][1] = 0; /* R(1) */
|
// DataMatrix[0][1] = 0; /* R(1) */
|
||||||
DataMatrix[0][2] = 0; /* R(0) */
|
// DataMatrix[0][2] = 0; /* R(0) */
|
||||||
|
|
||||||
/* Init the Hamming (15,11,3) library
|
/* Init the Hamming (15,11,3) library
|
||||||
* Not needed because it has already been done
|
* Not needed because it has already been done
|
||||||
@@ -356,6 +355,14 @@ uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* R(0) to R(2) may be used to transport some
|
||||||
|
* Restricted Access System (RAS) information,
|
||||||
|
* So save these three bits after hamming correction
|
||||||
|
* See patent US 2013/0288643 A1 */
|
||||||
|
R[0] = DataMatrix[0][2]; /* Save R(0) */
|
||||||
|
R[1] = DataMatrix[0][1]; /* Save R(1) */
|
||||||
|
R[2] = DataMatrix[0][0]; /* Save R(2) */
|
||||||
|
|
||||||
/* Return the number of irrecoverable Hamming errors */
|
/* Return the number of irrecoverable Hamming errors */
|
||||||
return HammingIrrecoverableErrorNb;
|
return HammingIrrecoverableErrorNb;
|
||||||
} /* End BPTC_196x96_Extract_Data() */
|
} /* End BPTC_196x96_Extract_Data() */
|
||||||
@@ -498,33 +505,38 @@ uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDat
|
|||||||
* DMRDataExtracted[11..15] = Hamming data
|
* DMRDataExtracted[11..15] = Hamming data
|
||||||
* DMRDataExtracted[16..31] = 16 bits of odd parity (to be checked)
|
* DMRDataExtracted[16..31] = 16 bits of odd parity (to be checked)
|
||||||
*
|
*
|
||||||
|
* @param ParityCheckTypeOdd : 0 = Parity to check is even (used in Non-Reverse Channel Single Burst BPTC)
|
||||||
|
* 1 = Parity to check is odd (used in Reverse Channel Single Burst BPTC)
|
||||||
|
*
|
||||||
* @return 0 = All is OK
|
* @return 0 = All is OK
|
||||||
* Other = Error - Irrecoverable Hamming parity check error number
|
* Other = Error - Irrecoverable Hamming parity check error number
|
||||||
*/
|
*/
|
||||||
uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32])
|
uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32], uint32_t ParityCheckTypeOdd)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint8_t DataMatrix[32];
|
uint8_t DataMatrix[32];
|
||||||
uint8_t LineUncorrected[16];
|
uint8_t LineUncorrected[16];
|
||||||
uint8_t LineCorrected[11];
|
uint8_t LineCorrected[11];
|
||||||
uint32_t HammingIrrecoverableErrorNb = 0;
|
uint32_t HammingIrrecoverableErrorNb = 0;
|
||||||
uint32_t ParityCheckErrorNb = 0;
|
uint32_t ParityCheckOddErrorNb = 0;
|
||||||
|
uint32_t ParityCheckEvenErrorNb = 0;
|
||||||
|
|
||||||
|
//TODO: make this so we can load either rc interleave, or single burst interleave
|
||||||
for(i = 0; i < 32; i++)
|
for(i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
DataMatrix[DeInterleaveReverseChannelBptc[i]] = InputInterleavedData[i] & 1;
|
DataMatrix[DeInterleaveReverseChannelBptcPlacement[DeInterleaveReverseChannelBptc[i]]] = InputInterleavedData[i] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the entire input buffer to the output buffer */
|
/* Copy the entire input buffer to the output buffer */
|
||||||
for(i = 0; i < 32; i++)
|
for(i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
DMRDataExtracted[i] = DataMatrix[i];
|
DMRDataExtracted[i] = DataMatrix[i] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare the line to be corrected */
|
/* Prepare the line to be corrected */
|
||||||
for(i = 0; i < 16; i++)
|
for(i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
LineUncorrected[i] = DataMatrix[i];
|
LineUncorrected[i] = DataMatrix[i] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply Hamming (16,11,4) code correction */
|
/* Apply Hamming (16,11,4) code correction */
|
||||||
@@ -536,7 +548,7 @@ uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDat
|
|||||||
/* Copy the corrected content to the output buffer */
|
/* Copy the corrected content to the output buffer */
|
||||||
for(i = 0; i < 11; i++)
|
for(i = 0; i < 11; i++)
|
||||||
{
|
{
|
||||||
DMRDataExtracted[i] = LineCorrected[i];
|
DMRDataExtracted[i] = LineCorrected[i] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check Parity bits */
|
/* Check Parity bits */
|
||||||
@@ -544,14 +556,24 @@ uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDat
|
|||||||
{
|
{
|
||||||
/* Odd parity ==> If data = 1 then parity = 0
|
/* Odd parity ==> If data = 1 then parity = 0
|
||||||
* If data = 0 then parity = 1 */
|
* If data = 0 then parity = 1 */
|
||||||
if(DMRDataExtracted[i] == DMRDataExtracted[i + 16]) ParityCheckErrorNb++;
|
if((DMRDataExtracted[i] & 1) == (DMRDataExtracted[i + 16] & 1)) ParityCheckOddErrorNb++;
|
||||||
|
if((DMRDataExtracted[i] & 1) != (DMRDataExtracted[i + 16] & 1)) ParityCheckEvenErrorNb++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprintf(stderr, "Hamming ERR=%u ; Parity ERR=%u", HammingIrrecoverableErrorNb, ParityCheckErrorNb);
|
//fprintf(stderr, "Hamming ERR=%u ; Parity odd ERR=%u, Parity even ERR=%u, ", HammingIrrecoverableErrorNb, ParityCheckOddErrorNb, ParityCheckEvenErrorNb);
|
||||||
|
|
||||||
|
//fprintf(stderr, "Content =\n");
|
||||||
|
//for(i = 0; i < 32; i++)
|
||||||
|
//{
|
||||||
|
// fprintf(stderr, "%u", DMRDataExtracted[i] & 1);
|
||||||
|
// if((i == 15) || (i == 31)) fprintf(stderr, "\n");
|
||||||
|
// else fprintf(stderr, "-");
|
||||||
|
//}
|
||||||
|
|
||||||
/* Return the number of irrecoverable Hamming errors +
|
/* Return the number of irrecoverable Hamming errors +
|
||||||
* the number of parity check error */
|
* the number of parity check error */
|
||||||
return (HammingIrrecoverableErrorNb + ParityCheckErrorNb);
|
if(ParityCheckTypeOdd) return (HammingIrrecoverableErrorNb + ParityCheckOddErrorNb);
|
||||||
|
else return (HammingIrrecoverableErrorNb + ParityCheckEvenErrorNb);
|
||||||
|
|
||||||
} /* End BPTC_16x2_Extract_Data() */
|
} /* End BPTC_16x2_Extract_Data() */
|
||||||
|
|
||||||
|
|||||||
134
src/dmr_block.c
134
src/dmr_block.c
@@ -51,7 +51,14 @@ void dmr_dheader (dsd_opts * opts, dsd_state * state, uint8_t dheader[], uint32_
|
|||||||
|
|
||||||
if ( (state->data_header_format[slot] & 0xF) == 0xD) //DD_HEAD
|
if ( (state->data_header_format[slot] & 0xF) == 0xD) //DD_HEAD
|
||||||
{
|
{
|
||||||
state->data_conf_data[slot] = 0;
|
//The Response Requested (A) information element of the header shall be set to 0 for unconfirmed data and shall be set
|
||||||
|
//to 1 for confirmed data. ETSI TS 102 361-3 V1.2.1 (2013-07) - 6.1.2
|
||||||
|
if ( (state->data_header_format[slot] & 0x40) == 0x40 && state->data_p_head[slot] == 0) //check response req bit
|
||||||
|
{
|
||||||
|
state->data_conf_data[slot] = 1;
|
||||||
|
}
|
||||||
|
else state->data_conf_data[slot] = 0;
|
||||||
|
|
||||||
state->data_header_padding[slot] = dheader[7] & 0xF;
|
state->data_header_padding[slot] = dheader[7] & 0xF;
|
||||||
state->data_header_blocks[slot] = ( (dheader[0] & 0x30) | ((dheader[1] & 0xF) >> 0) ); //what a pain MSB | LSB
|
state->data_header_blocks[slot] = ( (dheader[0] & 0x30) | ((dheader[1] & 0xF) >> 0) ); //what a pain MSB | LSB
|
||||||
fprintf (stderr, "\n Short Data - Defined: DPF %01X - SAP %02X - Appended Blocks %02X - Padding Bits %02X",
|
fprintf (stderr, "\n Short Data - Defined: DPF %01X - SAP %02X - Appended Blocks %02X - Padding Bits %02X",
|
||||||
@@ -61,7 +68,14 @@ void dmr_dheader (dsd_opts * opts, dsd_state * state, uint8_t dheader[], uint32_
|
|||||||
|
|
||||||
if ( (state->data_header_format[slot] & 0xF) == 0xE) //SP_HEAD or R_HEAD
|
if ( (state->data_header_format[slot] & 0xF) == 0xE) //SP_HEAD or R_HEAD
|
||||||
{
|
{
|
||||||
state->data_conf_data[slot] = 0;
|
//The Response Requested (A) information element of the header shall be set to 0 for unconfirmed data and shall be set
|
||||||
|
//to 1 for confirmed data. ETSI TS 102 361-3 V1.2.1 (2013-07) - 6.2.2
|
||||||
|
if ( (state->data_header_format[slot] & 0x40) == 0x40 && state->data_p_head[slot] == 0) //check response req bit
|
||||||
|
{
|
||||||
|
state->data_conf_data[slot] = 1;
|
||||||
|
}
|
||||||
|
else state->data_conf_data[slot] = 0;
|
||||||
|
|
||||||
state->data_header_padding[slot] = dheader[7] & 0xF;
|
state->data_header_padding[slot] = dheader[7] & 0xF;
|
||||||
state->data_header_blocks[slot] = ( (dheader[0] & 0x30) | ((dheader[1] & 0xF) >> 0) );
|
state->data_header_blocks[slot] = ( (dheader[0] & 0x30) | ((dheader[1] & 0xF) >> 0) );
|
||||||
fprintf (stderr, "\n Short Data - Raw or Precoded: DPF %01X - SAP %02X - Appended Blocks %02X - Padding Bits %02X",
|
fprintf (stderr, "\n Short Data - Raw or Precoded: DPF %01X - SAP %02X - Appended Blocks %02X - Padding Bits %02X",
|
||||||
@@ -247,11 +261,11 @@ void dmr_dheader (dsd_opts * opts, dsd_state * state, uint8_t dheader[], uint32_
|
|||||||
fprintf (stderr, "%s ", KNRM);
|
fprintf (stderr, "%s ", KNRM);
|
||||||
|
|
||||||
//let user know the data header may have errors
|
//let user know the data header may have errors
|
||||||
fprintf (stderr, "%s", KRED);
|
// fprintf (stderr, "%s", KRED);
|
||||||
if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
|
// if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
|
||||||
else if(IrrecoverableErrors == 0) fprintf(stderr, " (FEC OK)");
|
// else if(IrrecoverableErrors == 0) fprintf(stderr, " (FEC OK)");
|
||||||
else fprintf(stderr, " (FEC/CRC ERR)");
|
// else fprintf(stderr, " (FEC/CRC ERR)");
|
||||||
fprintf (stderr, "%s", KNRM);
|
// fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,16 +275,17 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
int i, j, k;
|
int i, j, k;
|
||||||
uint8_t lb = 0; //mbc last block
|
uint8_t lb = 0; //mbc last block
|
||||||
uint8_t pf = 0; //mbc protect flag
|
uint8_t pf = 0; //mbc protect flag
|
||||||
uint8_t is_conf_data = 0; //internal flag to see if type 1 blocks contain confirmed data crcs and serials
|
// uint8_t is_conf_data = 0; //internal flag to see if type 1 blocks contain confirmed data crcs and serials
|
||||||
uint8_t slot = state->currentslot;
|
uint8_t slot = state->currentslot;
|
||||||
int blocks;
|
int blocks;
|
||||||
uint8_t blockcounter = state->data_block_counter[slot];
|
uint8_t blockcounter = state->data_block_counter[slot];
|
||||||
|
uint8_t block_num = state->data_header_blocks[slot];
|
||||||
|
|
||||||
//crc specific variables
|
//crc specific variables
|
||||||
uint8_t len = 24; //len of completed message needing crc32 number of blocks*block_len - 12?
|
// uint8_t len = 24;
|
||||||
uint8_t crclen = 32; //len of the crc32 (obviously)
|
// uint8_t crclen = 32; //len of the crc32 (obviously)
|
||||||
uint8_t start = 12; //starting position (+12 offset loaded up data header)
|
// uint8_t start = 12; //starting position (+12 offset loaded up data header)
|
||||||
uint8_t n = 12; //number of bytes per block
|
// uint8_t n = 12; //number of bytes per block
|
||||||
|
|
||||||
//TODO: CRC check on Header, Blocks and full frames as appropriate
|
//TODO: CRC check on Header, Blocks and full frames as appropriate
|
||||||
uint32_t CRCCorrect = 0;
|
uint32_t CRCCorrect = 0;
|
||||||
@@ -278,7 +293,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
uint32_t CRCExtracted = 0;
|
uint32_t CRCExtracted = 0;
|
||||||
uint32_t IrrecoverableErrors = 0;
|
uint32_t IrrecoverableErrors = 0;
|
||||||
|
|
||||||
uint8_t dmr_pdu_sf_bits[18*8*8]; //8 blocks at 18 bytes at 8 bits //just a large value to have plenty storage space
|
uint8_t dmr_pdu_sf_bits[8*8*50]; //give plenty of space so we don't go oob
|
||||||
|
|
||||||
//MBC Header and Block CRC
|
//MBC Header and Block CRC
|
||||||
uint8_t mbc_crc_good[2]; //header and blocks crc pass/fail local storage
|
uint8_t mbc_crc_good[2]; //header and blocks crc pass/fail local storage
|
||||||
@@ -293,7 +308,8 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
if (block_len == 0) block_len = 18;
|
if (block_len == 0) block_len = 18;
|
||||||
if (block_len > 24) block_len = 24;
|
if (block_len > 24) block_len = 24;
|
||||||
|
|
||||||
//TODO: add CRC/FEC validation to each data header and each confirmed data block as well - type 1
|
//WIP: CRC32 on Completed Message Working! CRC9 on 3/4 Working! CRC9 or 1/2 and 1 still need testing - type 1
|
||||||
|
//may/will still fail on p_head data and blocks
|
||||||
if (type == 1)
|
if (type == 1)
|
||||||
{
|
{
|
||||||
//type 1 data block, shuffle method
|
//type 1 data block, shuffle method
|
||||||
@@ -312,8 +328,79 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
//time to send the completed 'superframe' to the DMR PDU message handler
|
//time to send the completed 'superframe' to the DMR PDU message handler
|
||||||
if (state->data_block_counter[slot] == state->data_header_blocks[slot])
|
if (state->data_block_counter[slot] == state->data_header_blocks[slot])
|
||||||
{
|
{
|
||||||
//TODO: CRC32 on completed messages
|
//CRC32 on completed messages
|
||||||
dmr_pdu (opts, state, block_len, state->dmr_pdu_sf[slot]);
|
for(i = 0, j = 0; i < (block_num * block_len); i++, j+=8)
|
||||||
|
{
|
||||||
|
dmr_pdu_sf_bits[j + 0] = (state->dmr_pdu_sf[slot][i] >> 7) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 1] = (state->dmr_pdu_sf[slot][i] >> 6) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 2] = (state->dmr_pdu_sf[slot][i] >> 5) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 3] = (state->dmr_pdu_sf[slot][i] >> 4) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 4] = (state->dmr_pdu_sf[slot][i] >> 3) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 5] = (state->dmr_pdu_sf[slot][i] >> 2) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 6] = (state->dmr_pdu_sf[slot][i] >> 1) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 7] = (state->dmr_pdu_sf[slot][i] >> 0) & 0x01;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//sanity check to prevent a negative or zero block_num or sending a negative value into the bit array
|
||||||
|
if (block_num < 1 || block_num == 0) block_num = 1;
|
||||||
|
|
||||||
|
CRCExtracted = 0;
|
||||||
|
//extract crc from last block, apply to completed 'superframe' minus header
|
||||||
|
for(i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
CRCExtracted = CRCExtracted << 1;
|
||||||
|
CRCExtracted = CRCExtracted | (uint32_t)(dmr_pdu_sf_bits[i + (block_len * 8) * block_num - 32] & 1); //96
|
||||||
|
}
|
||||||
|
|
||||||
|
//rearrage for ridiculously stupid CRC32 LSO/MSO ordering
|
||||||
|
for(i = 0, j = 0; i < (block_num * block_len); i+=2, j+=16)
|
||||||
|
{
|
||||||
|
dmr_pdu_sf_bits[j + 0] = (state->dmr_pdu_sf[slot][i+1] >> 7) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 1] = (state->dmr_pdu_sf[slot][i+1] >> 6) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 2] = (state->dmr_pdu_sf[slot][i+1] >> 5) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 3] = (state->dmr_pdu_sf[slot][i+1] >> 4) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 4] = (state->dmr_pdu_sf[slot][i+1] >> 3) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 5] = (state->dmr_pdu_sf[slot][i+1] >> 2) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 6] = (state->dmr_pdu_sf[slot][i+1] >> 1) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 7] = (state->dmr_pdu_sf[slot][i+1] >> 0) & 0x01;
|
||||||
|
|
||||||
|
dmr_pdu_sf_bits[j + 8] = (state->dmr_pdu_sf[slot][i] >> 7) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 9] = (state->dmr_pdu_sf[slot][i] >> 6) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 10] = (state->dmr_pdu_sf[slot][i] >> 5) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 11] = (state->dmr_pdu_sf[slot][i] >> 4) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 12] = (state->dmr_pdu_sf[slot][i] >> 3) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 13] = (state->dmr_pdu_sf[slot][i] >> 2) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 14] = (state->dmr_pdu_sf[slot][i] >> 1) & 0x01;
|
||||||
|
dmr_pdu_sf_bits[j + 15] = (state->dmr_pdu_sf[slot][i] >> 0) & 0x01;
|
||||||
|
|
||||||
|
//increment extra 2 bytes on each nth byte (depends on data type 1/2, 3/4, 1) if conf data
|
||||||
|
if ( i == (block_len - 1) )
|
||||||
|
{
|
||||||
|
if (state->data_conf_data[slot] == 0) i+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//confirmed working now!
|
||||||
|
CRCComputed = (uint32_t)ComputeCrc32Bit(dmr_pdu_sf_bits, ( block_num * block_len * 8) - 32);
|
||||||
|
|
||||||
|
//if the CRC32 is correct, I think its fair to assume we don't need to worry about if the
|
||||||
|
//individual CRC9s are correct on confirmed data blocks (but we can confirm now that they are all good)
|
||||||
|
if (CRCComputed == CRCExtracted) CRCCorrect = 1;
|
||||||
|
|
||||||
|
//test only running on good CRC or CRC/RAS bypass (aggressive_framesync)
|
||||||
|
if (CRCCorrect || opts->aggressive_framesync == 0) dmr_pdu (opts, state, block_len, state->dmr_pdu_sf[slot]);
|
||||||
|
|
||||||
|
if (CRCCorrect) ; //print nothing
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, "\n Slot %d - Multi Block PDU Message CRC32 ERR", slot+1);
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
|
state->data_conf_data[slot] = 0; //flag off conf data flag
|
||||||
|
state->data_header_format[slot] = 0; //zero out so we don't keep ascii printing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +474,12 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
CRCCorrect = 1;
|
CRCCorrect = 1;
|
||||||
IrrecoverableErrors = 0;
|
IrrecoverableErrors = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf(stderr, " (CRC ERR)");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
//cspdu will only act on any fid/opcodes if good CRC to prevent falsing on control signalling
|
//cspdu will only act on any fid/opcodes if good CRC to prevent falsing on control signalling
|
||||||
dmr_cspdu (opts, state, dmr_pdu_sf_bits, state->dmr_pdu_sf[slot], CRCCorrect, IrrecoverableErrors);
|
dmr_cspdu (opts, state, dmr_pdu_sf_bits, state->dmr_pdu_sf[slot], CRCCorrect, IrrecoverableErrors);
|
||||||
@@ -398,7 +491,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
if (opts->payload == 1 && type == 1 && state->data_block_counter[slot] == state->data_header_blocks[slot])
|
if (opts->payload == 1 && type == 1 && state->data_block_counter[slot] == state->data_header_blocks[slot])
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KGRN);
|
fprintf (stderr, "%s", KGRN);
|
||||||
fprintf (stderr, "\n Multi Block PDU Superframe - Slot [%d]\n ", slot+1);
|
fprintf (stderr, "\n Slot %d - Multi Block PDU Message\n ", slot+1);
|
||||||
for (i = 0; i < ((blocks+1)*block_len); i++)
|
for (i = 0; i < ((blocks+1)*block_len); i++)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "[%02X]", state->dmr_pdu_sf[slot][i]);
|
fprintf (stderr, "[%02X]", state->dmr_pdu_sf[slot][i]);
|
||||||
@@ -407,6 +500,10 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
fprintf (stderr, "\n ");
|
fprintf (stderr, "\n ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//debug print
|
||||||
|
// fprintf (stderr, " CRC - EXT %X CMP %X", CRCExtracted, CRCComputed);
|
||||||
|
|
||||||
fprintf (stderr, "%s ", KNRM);
|
fprintf (stderr, "%s ", KNRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +511,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
|
|||||||
if (opts->payload == 1 && type == 2 && lb == 1)
|
if (opts->payload == 1 && type == 2 && lb == 1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KGRN);
|
fprintf (stderr, "%s", KGRN);
|
||||||
fprintf (stderr, "\n MBC Multi Block PDU Superframe - Slot [%d]\n ", slot+1);
|
fprintf (stderr, "\n Slot %d - Multi Block Control Message\n ", slot+1);
|
||||||
for (i = 0; i < ((blocks+1)*block_len); i++)
|
for (i = 0; i < ((blocks+1)*block_len); i++)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "[%02X]", state->dmr_pdu_sf[slot][i]);
|
fprintf (stderr, "[%02X]", state->dmr_pdu_sf[slot][i]);
|
||||||
@@ -459,4 +556,5 @@ void dmr_reset_blocks (dsd_opts * opts, dsd_state * state)
|
|||||||
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
||||||
memset (state->dmr_lrrp_source, 0, sizeof(state->dmr_lrrp_source));
|
memset (state->dmr_lrrp_source, 0, sizeof(state->dmr_lrrp_source));
|
||||||
memset (state->dmr_cach_fragment, 1, sizeof (state->dmr_cach_fragment));
|
memset (state->dmr_cach_fragment, 1, sizeof (state->dmr_cach_fragment));
|
||||||
|
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
|
||||||
}
|
}
|
||||||
94
src/dmr_bs.c
94
src/dmr_bs.c
@@ -41,6 +41,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
uint8_t internalslot;
|
uint8_t internalslot;
|
||||||
uint8_t vc1;
|
uint8_t vc1;
|
||||||
uint8_t vc2;
|
uint8_t vc2;
|
||||||
|
|
||||||
|
//assign as nonsensical numbers
|
||||||
|
uint8_t cc = 25;
|
||||||
|
uint8_t power = 9; //power and pre-emption indicator
|
||||||
|
uint8_t lcss = 9;
|
||||||
|
|
||||||
//would be ideal to grab all dibits and break them into bits to pass to new data handler?
|
//would be ideal to grab all dibits and break them into bits to pass to new data handler?
|
||||||
uint8_t dummy_bits[196];
|
uint8_t dummy_bits[196];
|
||||||
@@ -189,13 +194,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
//embedded link control
|
//embedded link control
|
||||||
if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E
|
if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E
|
||||||
{
|
{
|
||||||
state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
||||||
state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0
|
state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E
|
if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E
|
||||||
{
|
{
|
||||||
state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
||||||
state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0
|
state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0
|
||||||
@@ -265,6 +270,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
else fprintf (stderr,"Sync: -DMR ");
|
else fprintf (stderr,"Sync: -DMR ");
|
||||||
|
|
||||||
vc1 = 1;
|
vc1 = 1;
|
||||||
|
|
||||||
|
//close MBEout file - slot 1
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
if (internalslot == 1)
|
if (internalslot == 1)
|
||||||
{
|
{
|
||||||
@@ -276,6 +284,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
vc2 = 1;
|
vc2 = 1;
|
||||||
|
|
||||||
|
//close MBEout file - slot 2
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
}
|
}
|
||||||
dmr_data_sync (opts, state);
|
dmr_data_sync (opts, state);
|
||||||
skipcount++;
|
skipcount++;
|
||||||
@@ -294,9 +305,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
if ( (strcmp (sync, DMR_BS_VOICE_SYNC) != 0) && emb_ok == 0) goto END; //fprintf (stderr, "EMB BAD? ");
|
if ( (strcmp (sync, DMR_BS_VOICE_SYNC) != 0) && emb_ok == 0) goto END; //fprintf (stderr, "EMB BAD? ");
|
||||||
else if (emb_ok == 1)
|
else if (emb_ok == 1)
|
||||||
{
|
{
|
||||||
uint8_t cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
|
cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
|
||||||
uint8_t power = EmbeddedSignalling[4];
|
power = EmbeddedSignalling[4];
|
||||||
uint8_t lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
|
lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -312,12 +323,16 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
state->dmrburstL = 16;
|
state->dmrburstL = 16;
|
||||||
vc = vc1;
|
vc = vc1;
|
||||||
sprintf (light, "%s", " [SLOT1] slot2 ");
|
sprintf (light, "%s", " [SLOT1] slot2 ");
|
||||||
|
//open MBEout file - slot 1
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state->dmrburstR = 16;
|
state->dmrburstR = 16;
|
||||||
vc = vc2;
|
vc = vc2;
|
||||||
sprintf (light, "%s", " slot1 [SLOT2] ");
|
sprintf (light, "%s", " slot1 [SLOT2] ");
|
||||||
|
//open MBEout file - slot 2
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_fR == NULL)) openMbeOutFileR (opts, state);
|
||||||
}
|
}
|
||||||
if (opts->inverted_dmr == 0) sprintf (polarity, "%s", "+");
|
if (opts->inverted_dmr == 0) sprintf (polarity, "%s", "+");
|
||||||
else sprintf (polarity, "%s", "-");
|
else sprintf (polarity, "%s", "-");
|
||||||
@@ -329,6 +344,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
//process embedded link control
|
//process embedded link control
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
||||||
|
//check the single burst/reverse channel opportunity
|
||||||
|
dmr_sbrc (opts, state, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internalslot == 1 && vc2 == 6)
|
if (internalslot == 1 && vc2 == 6)
|
||||||
@@ -336,6 +353,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
//process embedded link control
|
//process embedded link control
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
||||||
|
//check the single burst/reverse channel opportunity
|
||||||
|
dmr_sbrc (opts, state, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here
|
if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here
|
||||||
@@ -382,12 +401,37 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
state->last_vc_sync_time = time(NULL);
|
state->last_vc_sync_time = time(NULL);
|
||||||
state->last_cc_sync_time = time(NULL);
|
state->last_cc_sync_time = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//'DSP' output to file
|
||||||
|
if (opts->use_dsp_output == 1)
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 98 ", internalslot+1); //'98' is CACH designation value
|
||||||
|
for (i = 0; i < 6; i++) //3 byte CACH
|
||||||
|
{
|
||||||
|
int cach_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", cach_byte);
|
||||||
|
}
|
||||||
|
fprintf (pFile, "\n%d 10 ", internalslot+1); //0x10 for voice burst
|
||||||
|
for (i = 6; i < 72; i++) //33 bytes, no CACH
|
||||||
|
{
|
||||||
|
int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", dsp_byte);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset err checks
|
//reset err checks
|
||||||
cach_err = 1;
|
cach_err = 1;
|
||||||
tact_okay = 0;
|
tact_okay = 0;
|
||||||
emb_ok = 0;
|
emb_ok = 0;
|
||||||
|
|
||||||
|
//reset emb components
|
||||||
|
cc = 25;
|
||||||
|
power = 9;
|
||||||
|
lcss = 9;
|
||||||
|
|
||||||
//Extra safeguards to break loop
|
//Extra safeguards to break loop
|
||||||
// if ( (vc1 > 7 && vc2 > 7) ) goto END;
|
// if ( (vc1 > 7 && vc2 > 7) ) goto END;
|
||||||
@@ -420,6 +464,10 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
|
|||||||
state->errs2R = 0;
|
state->errs2R = 0;
|
||||||
state->errs2 = 0;
|
state->errs2 = 0;
|
||||||
|
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
//if we have a tact or emb err, then produce sync pattern/err message
|
//if we have a tact or emb err, then produce sync pattern/err message
|
||||||
if (tact_okay != 1 || emb_ok != 1)
|
if (tact_okay != 1 || emb_ok != 1)
|
||||||
{
|
{
|
||||||
@@ -471,6 +519,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
uint8_t cach_err = 0;
|
uint8_t cach_err = 0;
|
||||||
uint8_t sync_okay = 1;
|
uint8_t sync_okay = 1;
|
||||||
|
|
||||||
|
uint8_t internalslot;
|
||||||
|
|
||||||
char cachdata[25];
|
char cachdata[25];
|
||||||
int cachInterleave[24] =
|
int cachInterleave[24] =
|
||||||
@@ -503,10 +552,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = *dibit_p;
|
dibit = *dibit_p;
|
||||||
dibit_p++;
|
dibit_p++;
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
{
|
|
||||||
dibit = (dibit ^ 2);
|
|
||||||
}
|
|
||||||
state->dmr_stereo_payload[i] = dibit;
|
state->dmr_stereo_payload[i] = dibit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +580,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->currentslot = tact_bits[1];
|
internalslot = state->currentslot = tact_bits[1];
|
||||||
|
|
||||||
//Setup for first AMBE Frame
|
//Setup for first AMBE Frame
|
||||||
|
|
||||||
@@ -601,6 +647,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 18; i++)
|
for(i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
|
state->dmr_stereo_payload[i+90] = dibit;
|
||||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
@@ -623,6 +670,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 36; i++)
|
for(i = 0; i < 36; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
|
state->dmr_stereo_payload[i+108] = dibit;
|
||||||
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
|
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
@@ -633,6 +681,26 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//'DSP' output to file
|
||||||
|
if (opts->use_dsp_output == 1)
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 98 ", internalslot+1); //'98' is CACH designation value
|
||||||
|
for (i = 0; i < 6; i++) //3 byte CACH
|
||||||
|
{
|
||||||
|
int cach_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", cach_byte);
|
||||||
|
}
|
||||||
|
fprintf (pFile, "\n%d 10 ", internalslot+1); //0x10 for "voice burst"
|
||||||
|
for (i = 6; i < 72; i++) //33 bytes, no CACH
|
||||||
|
{
|
||||||
|
int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", dsp_byte);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (stderr,"%s ", getTime());
|
fprintf (stderr,"%s ", getTime());
|
||||||
char polarity[3];
|
char polarity[3];
|
||||||
char light[18];
|
char light[18];
|
||||||
@@ -640,10 +708,14 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
if (state->currentslot == 0)
|
if (state->currentslot == 0)
|
||||||
{
|
{
|
||||||
sprintf (light, "%s", " [SLOT1] slot2 ");
|
sprintf (light, "%s", " [SLOT1] slot2 ");
|
||||||
|
//open MBEout file - slot 1
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf (light, "%s", " slot1 [SLOT2] ");
|
sprintf (light, "%s", " slot1 [SLOT2] ");
|
||||||
|
//open MBEout file - slot 2
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_fR == NULL)) openMbeOutFileR (opts, state);
|
||||||
}
|
}
|
||||||
if (opts->inverted_dmr == 0) sprintf (polarity, "%s", "+");
|
if (opts->inverted_dmr == 0) sprintf (polarity, "%s", "+");
|
||||||
else sprintf (polarity, "%s", "-");
|
else sprintf (polarity, "%s", "-");
|
||||||
@@ -665,7 +737,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||||
|
|
||||||
//collect the mi fragment
|
//collect the mi fragment
|
||||||
dmr_late_entry_mi_fragment (opts, state, 1, ambe_fr, ambe_fr2, ambe_fr3);
|
dmr_late_entry_mi_fragment (opts, state, 1, m1, m2, m3);
|
||||||
|
|
||||||
cach_err = dmr_cach (opts, state, cachdata);
|
cach_err = dmr_cach (opts, state, cachdata);
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
|
|||||||
486
src/dmr_csbk.c
486
src/dmr_csbk.c
@@ -234,7 +234,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " Move (C_MOVE) (TODO)");
|
fprintf (stderr, " Move (C_MOVE) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Aloha
|
//Aloha
|
||||||
@@ -372,10 +372,10 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " Clear (P_CLEAR) (TODO)");
|
fprintf (stderr, " Clear (P_CLEAR) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
//(P_PROTECT) - Could be a useful way of determining who is on the current timeslot p_kind 2
|
//(P_PROTECT)
|
||||||
if (csbk_o == 47)
|
if (csbk_o == 47)
|
||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
@@ -395,27 +395,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " Target [%08d] - Source [%08d]", target, source);
|
fprintf (stderr, " Target [%08d] - Source [%08d]", target, source);
|
||||||
|
|
||||||
//Illegally Parked is another way to say a private call is outbound on this channel
|
|
||||||
//so, we can use this as a form of 'link control'
|
|
||||||
if (p_kind == 2)
|
|
||||||
{
|
|
||||||
//don't set this if operating out of dmr mono or using call alert beep
|
|
||||||
if (opts->dmr_mono == 0 && opts->call_alert == 0)
|
|
||||||
{
|
|
||||||
if (state->currentslot == 0)
|
|
||||||
{
|
|
||||||
state->lasttg = target;
|
|
||||||
state->lastsrc = source;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state->lasttgR = target;
|
|
||||||
state->lastsrcR = source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csbk_o == 40) //0x28 //check to see if these are fid 0 only, or also in other manufacturer fids
|
if (csbk_o == 40) //0x28 //check to see if these are fid 0 only, or also in other manufacturer fids
|
||||||
@@ -545,28 +524,28 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " C_AHOY (TODO) ");
|
fprintf (stderr, " C_AHOY ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csbk_o == 42)
|
if (csbk_o == 42)
|
||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " P_MAINT (TODO) ");
|
fprintf (stderr, " P_MAINT ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csbk_o == 30)
|
if (csbk_o == 30)
|
||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " C_ACKVIT (TODO) ");
|
fprintf (stderr, " C_ACKVIT ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csbk_o == 31)
|
if (csbk_o == 31)
|
||||||
{
|
{
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, " C_RAND (TODO) ");
|
fprintf (stderr, " C_RAND ");
|
||||||
}
|
}
|
||||||
|
|
||||||
//tier 2 csbks
|
//tier 2 csbks
|
||||||
@@ -641,39 +620,55 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Capacity+ Section
|
//Reworked Cap+ for Multi Block FL PDU and Private/Data Calls
|
||||||
|
//experimental, but seems to be working well
|
||||||
if (csbk_fid == 0x10)
|
if (csbk_fid == 0x10)
|
||||||
{
|
{
|
||||||
//not quite sure how these tuning rules will go over
|
//Cap+ Channel Status PDU
|
||||||
//if they don't work so well, may just fall back to
|
|
||||||
//a 'follow rest channel on no sync' only approach
|
|
||||||
if (csbk_o == 0x3E)
|
if (csbk_o == 0x3E)
|
||||||
{
|
{
|
||||||
|
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
uint8_t fl = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 2);
|
|
||||||
uint8_t slot = cs_pdu_bits[18];
|
uint8_t fl = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 2);
|
||||||
uint8_t rest_channel = cs_pdu[2] & 0xF; //0xF, or 0x1F?
|
uint8_t ts = cs_pdu_bits[18]; //timeslot this PDU occurs in
|
||||||
|
uint8_t res = cs_pdu_bits[19]; //unknown, always seems to be 0
|
||||||
|
uint8_t rest_channel = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[20], 4);
|
||||||
|
uint8_t group_tally = 0; //set this to the number of active group channels tallied
|
||||||
|
|
||||||
uint8_t ch[8]; //one bit per channel
|
uint8_t ch[8]; //one bit per channel
|
||||||
|
uint8_t pch[8]; //private or data call channel bits
|
||||||
uint8_t tg = 0;
|
uint8_t tg = 0;
|
||||||
uint32_t tghex = 0; //combined all tgs for debug
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
//tg and channel info for trunking purposes
|
//tg and channel info for trunking purposes
|
||||||
uint8_t t_tg[9];
|
uint8_t t_tg[9];
|
||||||
memset (t_tg, 0, sizeof(t_tg));
|
memset (t_tg, 0, sizeof(t_tg));
|
||||||
|
|
||||||
k = 0;
|
//initialize group ch and private/data channel bit arrays
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
ch[i] = 0;
|
||||||
|
pch[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//treating FL as a form of LCSS
|
||||||
|
if (fl != 1) //initial or single block (fl2 or fl3)
|
||||||
|
{
|
||||||
|
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
|
||||||
|
for (i = 0; i < 10*8; i++) state->cap_plus_csbk_bits[i] = cs_pdu_bits[i];
|
||||||
|
}
|
||||||
|
else //appended block (fl1)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 7*8; i++) state->cap_plus_csbk_bits[i+80] = cs_pdu_bits[i+24];
|
||||||
|
}
|
||||||
|
|
||||||
if (rest_channel != state->dmr_rest_channel)
|
if (rest_channel != state->dmr_rest_channel)
|
||||||
{
|
{
|
||||||
state->dmr_rest_channel = rest_channel;
|
state->dmr_rest_channel = rest_channel;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
ch[i] = cs_pdu_bits[i+24];
|
|
||||||
}
|
|
||||||
|
|
||||||
//assign to cc freq to follow during no sync
|
//assign to cc freq to follow during no sync
|
||||||
if (state->trunk_chan_map[rest_channel] != 0)
|
if (state->trunk_chan_map[rest_channel] != 0)
|
||||||
@@ -682,95 +677,297 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
//set to always tuned
|
//set to always tuned
|
||||||
opts->p25_is_tuned = 1;
|
opts->p25_is_tuned = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf (stderr, " Capacity Plus Channel Status - Rest Channel %d", rest_channel);
|
|
||||||
|
|
||||||
fprintf (stderr, "\n ");
|
fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest Channel %d", fl, ts, res, rest_channel);
|
||||||
for (i = 0; i < 8; i++)
|
if (fl == 1) fprintf (stderr, " - Appended Block");
|
||||||
|
if (fl == 2) fprintf (stderr, " - Initial Block");
|
||||||
|
if (fl == 3) fprintf (stderr, " - Single Block");
|
||||||
|
|
||||||
|
//look at each group channel bit -- run this PRIOR to checking private or data calls
|
||||||
|
//or else we will overwrite the ch bits we set below for private calls with zeroes
|
||||||
|
//these also seem to indicate data calls -- can't find a distinction of which is which
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Ch%d: ", i+1);
|
ch[i] = state->cap_plus_csbk_bits[i+24];
|
||||||
if (ch[i] != 0)
|
if (ch[i] == 1) group_tally++; //figure out where to start looking in the byte stream for the 0x80 flag
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for private/data calls
|
||||||
|
uint8_t pdflag = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[40+(group_tally*8)], 8); //seems to be 0x80 (last block flag?) on samples I have
|
||||||
|
uint16_t private_target = 0;
|
||||||
|
|
||||||
|
//first, check to see if we have a completed PDU
|
||||||
|
if (fl != 2)
|
||||||
|
{
|
||||||
|
//then check to see if this byte has a value, should be 0x80
|
||||||
|
//this bytes location seems to shift depending on level of activity
|
||||||
|
if (pdflag != 0) //now looking to see if any appended data was added
|
||||||
{
|
{
|
||||||
tg = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[k*8+32], 8);
|
k = 0; //= 0
|
||||||
fprintf (stderr, " %03d ", tg);
|
fprintf (stderr, "\n");
|
||||||
//add values to trunking tg/channel potentials
|
fprintf (stderr, " F%X Private or Data Call", pdflag);
|
||||||
t_tg[i] = tg;
|
for (int i = 0; i < 8; i++)
|
||||||
k++;
|
{
|
||||||
|
pch[i] = state->cap_plus_csbk_bits[i+48+(group_tally*8)];
|
||||||
|
if (pch[i] == 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, " Ch%d:", i+1);
|
||||||
|
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[56+(k*16)+(group_tally*8)], 16);
|
||||||
|
fprintf (stderr, " TGT %d;", private_target);
|
||||||
|
if (opts->trunk_tune_private_calls == 1) t_tg[i] = private_target; //set here for tuning allow/block
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end private/data call check
|
||||||
|
|
||||||
|
if (fl != 2)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "\n ");
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Ch%d: ", i+1);
|
||||||
|
if (ch[i] == 1) //group voice channels
|
||||||
|
{
|
||||||
|
tg = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[k*8+32], 8);
|
||||||
|
if (tg != 0) fprintf (stderr, " %03d ", tg);
|
||||||
|
else fprintf (stderr, "Actv ");
|
||||||
|
//add values to trunking tg/channel potentials
|
||||||
|
t_tg[i] = tg;
|
||||||
|
if (tg != 0) k++;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (pch[i] == 1) //private or data channels
|
||||||
|
{
|
||||||
|
fprintf (stderr, "P||D ");
|
||||||
|
//flag as available for tuning if enabled
|
||||||
|
if (opts->trunk_tune_private_calls == 1) ch[i] = 1;
|
||||||
|
}
|
||||||
|
else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
|
||||||
|
else fprintf (stderr, "Idle ");
|
||||||
|
|
||||||
|
if (i == 3) fprintf (stderr, "\n ");
|
||||||
|
}
|
||||||
|
|
||||||
|
state->dmr_mfid = 0x10;
|
||||||
|
sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
|
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
||||||
|
|
||||||
|
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
|
||||||
|
sprintf(state->dmr_site_parms, "%s", "");
|
||||||
|
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
|
//Skip tuning group calls if group calls are disabled
|
||||||
|
if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
|
||||||
|
|
||||||
|
//don't tune if vc on the current channel
|
||||||
|
if ( (time(NULL) - state->last_vc_sync_time > 2) )
|
||||||
|
{
|
||||||
|
for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
|
||||||
|
{
|
||||||
|
char mode[8]; //allow, block, digital, enc, etc
|
||||||
|
|
||||||
|
//if we are using allow/whitelist mode, then write 'B' to mode for block
|
||||||
|
//comparison below will look for an 'A' to write to mode if it is allowed
|
||||||
|
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
|
||||||
|
|
||||||
|
for (int i = 0; i < state->group_tally; i++)
|
||||||
|
{
|
||||||
|
if (state->group_array[i].groupNumber == t_tg[j])
|
||||||
|
{
|
||||||
|
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||||
|
strcpy (mode, state->group_array[i].groupMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//without priority, this will tune the first one it finds (if group isn't blocked)
|
||||||
|
if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
|
||||||
|
{
|
||||||
|
if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
|
||||||
|
{
|
||||||
|
//RIGCTL
|
||||||
|
if (opts->use_rigctl == 1)
|
||||||
|
{
|
||||||
|
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
||||||
|
SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
|
||||||
|
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
||||||
|
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
|
||||||
|
j = 11; //break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
//rtl_udp
|
||||||
|
else if (opts->audio_in_type == 3)
|
||||||
|
{
|
||||||
|
rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
|
||||||
|
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
||||||
|
opts->p25_is_tuned = 1;
|
||||||
|
j = 11; //break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} //end tuning
|
||||||
|
|
||||||
|
SKIPCAP: ;
|
||||||
|
//debug print
|
||||||
|
if (fl == 1 && opts->payload == 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s\n", KYEL);
|
||||||
|
fprintf (stderr, " CAP+ Multi Block PDU ");
|
||||||
|
uint8_t fl_bytes = 0;
|
||||||
|
for (i = 0; i < 17; i++)
|
||||||
|
{
|
||||||
|
fl_bytes = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[i*8], 8);
|
||||||
|
fprintf (stderr, "[%02X]", fl_bytes);
|
||||||
|
}
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
|
||||||
|
|
||||||
|
} //fl != 2
|
||||||
|
} //opcode == 0x3E
|
||||||
|
} //fid == 0x10
|
||||||
|
|
||||||
|
//Capacity+ Section -- fallback if issues arise
|
||||||
|
// if (csbk_fid == 0x10)
|
||||||
|
// {
|
||||||
|
// //not quite sure how these tuning rules will go over
|
||||||
|
// //if they don't work so well, may just fall back to
|
||||||
|
// //a 'follow rest channel on no sync' only approach
|
||||||
|
// if (csbk_o == 0x3E)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// //initial line break
|
||||||
|
// fprintf (stderr, "\n");
|
||||||
|
// fprintf (stderr, "%s", KYEL);
|
||||||
|
|
||||||
|
// uint8_t fl = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 2);
|
||||||
|
// uint8_t ts = cs_pdu_bits[18]; //accurate?
|
||||||
|
// uint8_t res = cs_pdu_bits[19]; //unknown??
|
||||||
|
// uint8_t rest_channel = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[20], 4);
|
||||||
|
|
||||||
|
// uint8_t ch[8]; //one bit per channel
|
||||||
|
// uint8_t tg = 0;
|
||||||
|
// uint32_t tghex = 0; //combined all tgs for debug
|
||||||
|
// int i, j, k;
|
||||||
|
|
||||||
|
// //tg and channel info for trunking purposes
|
||||||
|
// uint8_t t_tg[9];
|
||||||
|
// memset (t_tg, 0, sizeof(t_tg));
|
||||||
|
|
||||||
|
// k = 0;
|
||||||
|
// if (rest_channel != state->dmr_rest_channel)
|
||||||
|
// {
|
||||||
|
// state->dmr_rest_channel = rest_channel;
|
||||||
|
// }
|
||||||
|
// for (int i = 0; i < 8; i++)
|
||||||
|
// {
|
||||||
|
// ch[i] = cs_pdu_bits[i+24];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //assign to cc freq to follow during no sync
|
||||||
|
// if (state->trunk_chan_map[rest_channel] != 0)
|
||||||
|
// {
|
||||||
|
// state->p25_cc_freq = state->trunk_chan_map[rest_channel];
|
||||||
|
// //set to always tuned
|
||||||
|
// opts->p25_is_tuned = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest Channel %d", fl, ts, res, rest_channel);
|
||||||
|
|
||||||
|
// fprintf (stderr, "\n ");
|
||||||
|
// for (i = 0; i < 8; i++)
|
||||||
|
// {
|
||||||
|
// fprintf (stderr, "Ch%d: ", i+1);
|
||||||
|
// if (ch[i] != 0)
|
||||||
|
// {
|
||||||
|
// tg = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[k*8+32], 8);
|
||||||
|
// if (tg != 0) fprintf (stderr, " %03d ", tg);
|
||||||
|
// else fprintf (stderr, "Priv "); //observed 000s for TG value seem to appear during a Cap+ Private TXI call
|
||||||
|
// //add values to trunking tg/channel potentials
|
||||||
|
// t_tg[i] = tg;
|
||||||
|
// k++;
|
||||||
|
|
||||||
}
|
// }
|
||||||
else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
|
// else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
|
||||||
else fprintf (stderr, "Idle ");
|
// else fprintf (stderr, "Idle ");
|
||||||
|
|
||||||
if (i == 3) fprintf (stderr, "\n ");
|
// if (i == 3) fprintf (stderr, "\n ");
|
||||||
}
|
// }
|
||||||
tghex = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
|
// tghex = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
|
||||||
//fprintf (stderr, "\n TG Hex = 0x%06X", tghex);
|
// //fprintf (stderr, "\n TG Hex = 0x%06X", tghex);
|
||||||
state->dmr_mfid = 0x10;
|
// state->dmr_mfid = 0x10;
|
||||||
sprintf (state->dmr_branding, "%s", "Motorola");
|
// sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
||||||
|
|
||||||
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
|
// //nullify any previous TIII data (bugfix for bad assignments or system type switching)
|
||||||
sprintf(state->dmr_site_parms, "%s", "");
|
// sprintf(state->dmr_site_parms, "%s", "");
|
||||||
|
|
||||||
fprintf (stderr, "%s", KNRM);
|
// fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
//Skip tuning group calls if group calls are disabled
|
// //Skip tuning group calls if group calls are disabled
|
||||||
if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
|
// if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
|
||||||
|
|
||||||
//don't tune if currently a vc on the current channel
|
// //don't tune if currently a vc on the current channel
|
||||||
if ( (time(NULL) - state->last_vc_sync_time > 2) )
|
// if ( (time(NULL) - state->last_vc_sync_time > 2) )
|
||||||
{
|
// {
|
||||||
for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
|
// for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
|
||||||
{
|
// {
|
||||||
char mode[8]; //allow, block, digital, enc, etc
|
// char mode[8]; //allow, block, digital, enc, etc
|
||||||
|
|
||||||
//if we are using allow/whitelist mode, then write 'B' to mode for block
|
// //if we are using allow/whitelist mode, then write 'B' to mode for block
|
||||||
//comparison below will look for an 'A' to write to mode if it is allowed
|
// //comparison below will look for an 'A' to write to mode if it is allowed
|
||||||
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
|
// if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
|
||||||
|
|
||||||
for (int i = 0; i < state->group_tally; i++)
|
// for (int i = 0; i < state->group_tally; i++)
|
||||||
{
|
// {
|
||||||
if (state->group_array[i].groupNumber == t_tg[j])
|
// if (state->group_array[i].groupNumber == t_tg[j])
|
||||||
{
|
// {
|
||||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
// fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||||
strcpy (mode, state->group_array[i].groupMode);
|
// strcpy (mode, state->group_array[i].groupMode);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//no more 0 reporting, that was some bad code that caused that issue
|
// //no more 0 reporting, that was some bad code that caused that issue
|
||||||
//without priority, this will tune the first one it finds (if group isn't blocked)
|
// //without priority, this will tune the first one it finds (if group isn't blocked)
|
||||||
if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
|
// if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
|
||||||
{
|
// {
|
||||||
if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
|
// if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
|
||||||
{
|
// {
|
||||||
//RIGCTL
|
// //RIGCTL
|
||||||
if (opts->use_rigctl == 1)
|
// if (opts->use_rigctl == 1)
|
||||||
{
|
// {
|
||||||
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
// if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
||||||
SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
|
// SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
|
||||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
// state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
||||||
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
|
// opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
|
||||||
j = 11; //break loop
|
// j = 11; //break loop
|
||||||
}
|
// }
|
||||||
|
|
||||||
//rtl_udp
|
// //rtl_udp
|
||||||
else if (opts->audio_in_type == 3)
|
// else if (opts->audio_in_type == 3)
|
||||||
{
|
// {
|
||||||
rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
|
// rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
|
||||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
// state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
|
||||||
opts->p25_is_tuned = 1;
|
// opts->p25_is_tuned = 1;
|
||||||
j = 11; //break loop
|
// j = 11; //break loop
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
SKIPCAP: ; //do nothing
|
// SKIPCAP: ; //do nothing
|
||||||
}
|
// }
|
||||||
|
|
||||||
//Connect+ Section
|
//Connect+ Section
|
||||||
if (csbk_fid == 0x06)
|
if (csbk_fid == 0x06)
|
||||||
@@ -888,67 +1085,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//upon further examination, opcodes 6 and C (12) do not appear to be a channel grants or tlcs,
|
|
||||||
//it is present in Connect+, but its purpose isn't entirely clear
|
|
||||||
//DSDPlus only regards it as a 'CSBK [LB=1 CSBKO=6 (?) FID=06 v1=115213 v2=10488576 v3=0]
|
|
||||||
//unsure of what the v1 v2 v3 fields specify
|
|
||||||
// if (csbk_o == 0x06 || csbk_o == 0x0C)
|
|
||||||
if (csbk_o != 0x01 && csbk_o != 0x03)
|
|
||||||
{
|
|
||||||
|
|
||||||
uint32_t v1 = ( (cs_pdu[2] << 16) + (cs_pdu[3] << 8) + cs_pdu[4] );
|
|
||||||
uint32_t v2 = ( (cs_pdu[5] << 16) + (cs_pdu[6] << 8) + cs_pdu[7] );
|
|
||||||
uint32_t v3 = ( (cs_pdu[7] << 16) + (cs_pdu[8] << 8) + cs_pdu[9] );
|
|
||||||
|
|
||||||
// debug print
|
|
||||||
// initial line break
|
|
||||||
// fprintf (stderr, "\n");
|
|
||||||
// fprintf (stderr, "%s", KYEL);
|
|
||||||
// fprintf (stderr, " Connect Plus CSBK 0x%X\n", csbk_o);
|
|
||||||
// fprintf (stderr, " v1(%d), v2(%d), v3(%d)",v1, v2, v3);
|
|
||||||
// state->dmr_mfid = 0x06;
|
|
||||||
// sprintf (state->dmr_branding, "%s", "Motorola");
|
|
||||||
// sprintf(state->dmr_branding_sub, "Con+ ");
|
|
||||||
}
|
|
||||||
|
|
||||||
//the validity of these last three csbk opcodes cannot be confirmed
|
|
||||||
//I recall making these based on observation and speculation long ago,
|
|
||||||
//but cannot verify the accuracy of them now, so they will remain disabled
|
|
||||||
//they offer no particular interest to trunking/listening
|
|
||||||
|
|
||||||
// if (csbk_o == 0x11)
|
|
||||||
// {
|
|
||||||
// //initial line break
|
|
||||||
// fprintf (stderr, "\n");
|
|
||||||
// fprintf (stderr, "%s", KYEL);
|
|
||||||
// fprintf (stderr, " Connect Plus Registration Request");
|
|
||||||
// state->dmr_mfid = 0x06;
|
|
||||||
// sprintf (state->dmr_branding, "%s", "Motorola");
|
|
||||||
// sprintf(state->dmr_branding_sub, "Con+ ");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (csbk_o == 0x12)
|
|
||||||
// {
|
|
||||||
// //initial line break
|
|
||||||
// fprintf (stderr, "\n");
|
|
||||||
// fprintf (stderr, "%s", KYEL);
|
|
||||||
// fprintf (stderr, " Connect Plus Registration Response");
|
|
||||||
// state->dmr_mfid = 0x06;
|
|
||||||
// sprintf (state->dmr_branding, "%s", "Motorola");
|
|
||||||
// sprintf(state->dmr_branding_sub, "Con+ ");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (csbk_o == 0x18)
|
|
||||||
// {
|
|
||||||
// //initial line break
|
|
||||||
// fprintf (stderr, "\n");
|
|
||||||
// fprintf (stderr, "%s", KYEL);
|
|
||||||
// fprintf (stderr, " Connect Plus Talkgroup Affiliation");
|
|
||||||
// state->dmr_mfid = 0x06;
|
|
||||||
// sprintf (state->dmr_branding, "%s", "Motorola");
|
|
||||||
// sprintf(state->dmr_branding_sub, "Con+ ");
|
|
||||||
// }
|
|
||||||
|
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[i];
|
dibit = (int)state->dmr_stereo_payload[i];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[i] = dibit;
|
||||||
|
|
||||||
cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
||||||
cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
||||||
@@ -103,6 +104,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[i+12];
|
dibit = (int)state->dmr_stereo_payload[i+12];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[i+12] = dibit;
|
||||||
info[2*i] = (1 & (dibit >> 1)); // bit 1
|
info[2*i] = (1 & (dibit >> 1)); // bit 1
|
||||||
info[(2*i)+1] = (1 & dibit); // bit 0
|
info[(2*i)+1] = (1 & dibit); // bit 0
|
||||||
}
|
}
|
||||||
@@ -118,6 +120,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[61];
|
dibit = (int)state->dmr_stereo_payload[61];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[61] = dibit;
|
||||||
|
|
||||||
SlotType[0] = (1 & (dibit >> 1)); // bit 1
|
SlotType[0] = (1 & (dibit >> 1)); // bit 1
|
||||||
SlotType[1] = (1 & dibit); // bit 0
|
SlotType[1] = (1 & dibit); // bit 0
|
||||||
@@ -132,6 +135,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[62];
|
dibit = (int)state->dmr_stereo_payload[62];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[62] = dibit;
|
||||||
|
|
||||||
SlotType[2] = (1 & (dibit >> 1)); // bit 1
|
SlotType[2] = (1 & (dibit >> 1)); // bit 1
|
||||||
SlotType[3] = (1 & dibit); // bit 0
|
SlotType[3] = (1 & dibit); // bit 0
|
||||||
@@ -146,6 +150,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[63];
|
dibit = (int)state->dmr_stereo_payload[63];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[63] = dibit;
|
||||||
|
|
||||||
SlotType[4] = (1 & (dibit >> 1)); // bit 1
|
SlotType[4] = (1 & (dibit >> 1)); // bit 1
|
||||||
SlotType[5] = (1 & dibit); // bit 0
|
SlotType[5] = (1 & dibit); // bit 0
|
||||||
@@ -160,6 +165,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[64];
|
dibit = (int)state->dmr_stereo_payload[64];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[64] = dibit;
|
||||||
|
|
||||||
SlotType[6] = (1 & (dibit >> 1)); // bit 1
|
SlotType[6] = (1 & (dibit >> 1)); // bit 1
|
||||||
SlotType[7] = (1 & dibit); // bit 0
|
SlotType[7] = (1 & dibit); // bit 0
|
||||||
@@ -175,6 +181,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[65];
|
dibit = (int)state->dmr_stereo_payload[65];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[65] = dibit;
|
||||||
SlotType[8] = (1 & (dibit >> 1)); // bit 1
|
SlotType[8] = (1 & (dibit >> 1)); // bit 1
|
||||||
SlotType[9] = (1 & dibit); // bit 0
|
SlotType[9] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
@@ -191,6 +198,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = (int)state->dmr_stereo_payload[i+66];
|
dibit = (int)state->dmr_stereo_payload[i+66];
|
||||||
}
|
}
|
||||||
|
else state->dmr_stereo_payload[i+66] = dibit;
|
||||||
|
|
||||||
syncdata[2*i] = (1 & (dibit >> 1)); // bit 1
|
syncdata[2*i] = (1 & (dibit >> 1)); // bit 1
|
||||||
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
syncdata[(2*i)+1] = (1 & dibit); // bit 0
|
||||||
sync[i] = (dibit | 1) + 48;
|
sync[i] = (dibit | 1) + 48;
|
||||||
@@ -236,6 +245,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
if (state->dmr_stereo == 0)
|
if (state->dmr_stereo == 0)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
|
state->dmr_stereo_payload[i+90] = dibit;
|
||||||
}
|
}
|
||||||
if (state->dmr_stereo == 1)
|
if (state->dmr_stereo == 1)
|
||||||
{
|
{
|
||||||
@@ -277,6 +287,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
if (state->dmr_stereo == 0)
|
if (state->dmr_stereo == 0)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
|
state->dmr_stereo_payload[i+95] = dibit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->dmr_stereo == 1)
|
if (state->dmr_stereo == 1)
|
||||||
@@ -288,10 +299,11 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
|
|||||||
info[(2*i) + 99] = (1 & dibit); // bit 0
|
info[(2*i) + 99] = (1 & dibit); // bit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
dmr_data_burst_handler(opts, state, (uint8_t *)info, burst);
|
//don't run on MS Reverse Channel Data
|
||||||
|
if (state->dmr_ms_rc == 0) dmr_data_burst_handler(opts, state, (uint8_t *)info, burst);
|
||||||
|
|
||||||
//don't run cach on simplex or mono
|
//don't run cach on simplex or mono
|
||||||
if (state->dmr_ms_mode == 0 || opts->dmr_mono == 0)
|
if (state->dmr_ms_mode == 0 && opts->dmr_mono == 0)
|
||||||
{
|
{
|
||||||
cach_err = dmr_cach (opts, state, cachdata);
|
cach_err = dmr_cach (opts, state, cachdata);
|
||||||
}
|
}
|
||||||
|
|||||||
280
src/dmr_dburst.c
280
src/dmr_dburst.c
@@ -9,9 +9,9 @@
|
|||||||
* 2022-12 DSD-FME Florida Man Edition
|
* 2022-12 DSD-FME Florida Man Edition
|
||||||
*-----------------------------------------------------------------------------*/
|
*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//TODO: CRC9 on confirmed data blocks; CRC32 on completed data sf;
|
//WIP: CRC9 on confirmed data blocks; CRC32 on completed data sf;
|
||||||
//TODO: Reverse Channel Signalling - RC single burst BPTC/7-bit CRC
|
//WIP: Reverse Channel Signalling - RC single burst BPTC/7-bit CRC
|
||||||
//TODO: Single Burst Embedded LC - Non-RC single burst LC - Look for Late Entry Alg/Key
|
//WIP: Single Burst Embedded LC - Non-RC single burst LC - Look for Late Entry Alg/Key
|
||||||
|
|
||||||
#include "dsd.h"
|
#include "dsd.h"
|
||||||
|
|
||||||
@@ -26,6 +26,12 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
uint8_t slot = state->currentslot;
|
uint8_t slot = state->currentslot;
|
||||||
uint8_t block = state->data_block_counter[slot];
|
uint8_t block = state->data_block_counter[slot];
|
||||||
|
|
||||||
|
//confirmed data
|
||||||
|
uint8_t dbsn = 0; //data block serial number for confirmed data blocks
|
||||||
|
uint8_t blockcounter = 0; //local block count
|
||||||
|
uint8_t confdatabits[250]; //array to reshuffle conf data block bits into sequence for crc9 check
|
||||||
|
memset (confdatabits, 0, sizeof(confdatabits));
|
||||||
|
|
||||||
//BPTC 196x96 Specific
|
//BPTC 196x96 Specific
|
||||||
uint8_t BPTCDeInteleavedData[196];
|
uint8_t BPTCDeInteleavedData[196];
|
||||||
uint8_t BPTCDmrDataBit[96];
|
uint8_t BPTCDmrDataBit[96];
|
||||||
@@ -45,9 +51,11 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
|
|
||||||
uint8_t R[3];
|
uint8_t R[3];
|
||||||
uint8_t BPTCReservedBits = 0;
|
uint8_t BPTCReservedBits = 0;
|
||||||
|
uint8_t is_ras = 0;
|
||||||
|
uint8_t crc_original_validity = 0;
|
||||||
|
|
||||||
uint32_t crcmask = 0;
|
uint32_t crcmask = 0;
|
||||||
uint8_t crclen = 0;
|
uint8_t crclen = 0;
|
||||||
|
|
||||||
uint8_t is_bptc = 0;
|
uint8_t is_bptc = 0;
|
||||||
uint8_t is_trellis = 0;
|
uint8_t is_trellis = 0;
|
||||||
@@ -108,32 +116,31 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
pdu_len = 12; //12 bytes
|
pdu_len = 12; //12 bytes
|
||||||
sprintf(state->fsubtype, " DATA");
|
sprintf(state->fsubtype, " DATA");
|
||||||
break;
|
break;
|
||||||
//TODO - 1/2 0x0F0 - 3/4 0x1FF - Rate 1 0x10F
|
|
||||||
//going to set crclen and mask according to confirmed data here,
|
|
||||||
//use block assmebler to carry out completed message crc
|
|
||||||
case 0x07: //1/2 Rate Data
|
case 0x07: //1/2 Rate Data
|
||||||
is_bptc = 1;
|
is_bptc = 1;
|
||||||
crclen = 9; //confirmed data only
|
crclen = 9; //confirmed data only
|
||||||
crcmask = 0x0F0;
|
crcmask = 0x0F0;
|
||||||
pdu_len = 12; //12 bytes unconfirmed
|
pdu_len = 12; //12 bytes unconfirmed
|
||||||
|
sprintf(state->fsubtype, " R12U ");
|
||||||
if (state->data_conf_data[slot] == 1)
|
if (state->data_conf_data[slot] == 1)
|
||||||
{
|
{
|
||||||
pdu_len = 10;
|
pdu_len = 10;
|
||||||
pdu_start = 2; //start at plus two when assembling
|
pdu_start = 2; //start at plus two when assembling
|
||||||
|
sprintf(state->fsubtype, " R12C ");
|
||||||
}
|
}
|
||||||
sprintf(state->fsubtype, " R12D ");
|
|
||||||
break;
|
break;
|
||||||
case 0x08: //3/4 Rate Data
|
case 0x08: //3/4 Rate Data
|
||||||
is_trellis = 1;
|
is_trellis = 1;
|
||||||
crclen = 9; //confirmed data only
|
crclen = 9; //confirmed data only
|
||||||
crcmask = 0x1FF;
|
crcmask = 0x1FF;
|
||||||
pdu_len = 18; //18 bytes unconfirmed
|
pdu_len = 18; //18 bytes unconfirmed
|
||||||
|
sprintf(state->fsubtype, " R34U ");
|
||||||
if (state->data_conf_data[slot] == 1)
|
if (state->data_conf_data[slot] == 1)
|
||||||
{
|
{
|
||||||
pdu_len = 16;
|
pdu_len = 16;
|
||||||
pdu_start = 2; //start at plus two when assembling
|
pdu_start = 2; //start at plus two when assembling
|
||||||
|
sprintf(state->fsubtype, " R34C ");
|
||||||
}
|
}
|
||||||
sprintf(state->fsubtype, " R34D ");
|
|
||||||
break;
|
break;
|
||||||
case 0x09: //Idle
|
case 0x09: //Idle
|
||||||
//pseudo-random data fill, no need to do anything with this
|
//pseudo-random data fill, no need to do anything with this
|
||||||
@@ -141,10 +148,16 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
break;
|
break;
|
||||||
case 0x0A: //1 Rate Data
|
case 0x0A: //1 Rate Data
|
||||||
crclen = 9; //confirmed data only
|
crclen = 9; //confirmed data only
|
||||||
crcmask = 0x1FF;
|
crcmask = 0x10F;
|
||||||
is_full = 1;
|
is_full = 1;
|
||||||
pdu_len = 25; //196 bits - 24.5 bytes
|
pdu_len = 25; //196 bits - 24.5 bytes
|
||||||
sprintf(state->fsubtype, " R_1D ");
|
sprintf(state->fsubtype, " R_1U ");
|
||||||
|
if (state->data_conf_data[slot] == 1)
|
||||||
|
{
|
||||||
|
pdu_len = 23;
|
||||||
|
pdu_start = 2; //start at plus two when assembling
|
||||||
|
sprintf(state->fsubtype, " R_1C ");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0B: //Unified Data
|
case 0x0B: //Unified Data
|
||||||
is_bptc = 1;
|
is_bptc = 1;
|
||||||
@@ -153,13 +166,21 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
pdu_len = 12; //12 bytes
|
pdu_len = 12; //12 bytes
|
||||||
sprintf(state->fsubtype, " UDAT ");
|
sprintf(state->fsubtype, " UDAT ");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//special types (not real data 'sync' bursts)
|
//special types (not real data 'sync' bursts)
|
||||||
case 0xEB: //Embedded Signalling
|
case 0xEB: //Embedded Signalling
|
||||||
|
crclen = 5;
|
||||||
is_emb = 1;
|
is_emb = 1;
|
||||||
pdu_len = 9;
|
pdu_len = 9;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
//Slot Type FEC should catch this so we never see it,
|
||||||
|
//but if it doesn't, then we can still dump the entire 'packet'
|
||||||
|
//treat like rate 1 unconfirmed data
|
||||||
|
is_full = 1;
|
||||||
|
pdu_len = 25; //196 bits - 24.5 bytes
|
||||||
|
sprintf(state->fsubtype, " _UNK ");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -168,6 +189,26 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
{
|
{
|
||||||
if (state->dmr_ms_mode == 0) fprintf(stderr, "| Color Code=%02d ", state->dmr_color_code);
|
if (state->dmr_ms_mode == 0) fprintf(stderr, "| Color Code=%02d ", state->dmr_color_code);
|
||||||
fprintf(stderr, "|%s", state->fsubtype);
|
fprintf(stderr, "|%s", state->fsubtype);
|
||||||
|
|
||||||
|
//'DSP' output to file
|
||||||
|
if (opts->use_dsp_output == 1)
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 98 ", slot+1); //'98' is CACH designation value
|
||||||
|
for (i = 0; i < 6; i++) //3 byte CACH
|
||||||
|
{
|
||||||
|
int cach_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", cach_byte);
|
||||||
|
}
|
||||||
|
fprintf (pFile, "\n%d %02X ", slot+1, databurst); //use hex value of current data burst type
|
||||||
|
for (i = 6; i < 72; i++) //33 bytes, no CACH
|
||||||
|
{
|
||||||
|
int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", dsp_byte);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Most Data Sync Burst types will use the bptc 196x96
|
//Most Data Sync Burst types will use the bptc 196x96
|
||||||
@@ -184,7 +225,11 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
IrrecoverableErrors = BPTC_196x96_Extract_Data(BPTCDeInteleavedData, BPTCDmrDataBit, R);
|
IrrecoverableErrors = BPTC_196x96_Extract_Data(BPTCDeInteleavedData, BPTCDmrDataBit, R);
|
||||||
|
|
||||||
/* Fill the reserved bit (R(0)-R(2) of the BPTC(196,96) block) */
|
/* Fill the reserved bit (R(0)-R(2) of the BPTC(196,96) block) */
|
||||||
BPTCReservedBits = (R[0] & 0x01) | ((R[1] << 1) & 0x02) | ((R[2] << 2) & 0x08);
|
BPTCReservedBits = (R[0] & 0x01) | ((R[1] << 1) & 0x02) | ((R[2] << 2) & 0x04);
|
||||||
|
|
||||||
|
//debug print
|
||||||
|
//fprintf (stderr, " RAS? %X - %d %d %d", BPTCReservedBits, R[0], R[1], R[2]);
|
||||||
|
|
||||||
|
|
||||||
/* Convert the 96 bits BPTC data into 12 bytes */
|
/* Convert the 96 bits BPTC data into 12 bytes */
|
||||||
k = 0;
|
k = 0;
|
||||||
@@ -213,10 +258,39 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
/* Check/correct the BPTC data and compute the Reed-Solomon (12,9) CRC */
|
/* Check/correct the BPTC data and compute the Reed-Solomon (12,9) CRC */
|
||||||
if (is_lc) CRCCorrect = ComputeAndCorrectFullLinkControlCrc(BPTCDmrDataByte, &CRCComputed, crcmask);
|
if (is_lc) CRCCorrect = ComputeAndCorrectFullLinkControlCrc(BPTCDmrDataByte, &CRCComputed, crcmask);
|
||||||
|
|
||||||
//TODO: run CRC9 on confirmed 1/2 data blocks
|
//set CRC to correct on unconfirmed 1/2 data blocks (for reporting due to no CRC available on these)
|
||||||
else if (state->data_conf_data[slot] == 1)
|
else if (state->data_conf_data[slot] == 0 && databurst == 0x7)
|
||||||
{
|
{
|
||||||
//run CRC on individual blocks according to type and validate each individual block
|
CRCComputed = 0;
|
||||||
|
CRCExtracted = 0;
|
||||||
|
CRCCorrect = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set CRC to correct on proprietary data header blocks (unsure if p_head data has valid crcs,
|
||||||
|
//may be ras enabled, manufacturer specific, or none, currently unknown, but possibly RAS on samples I have)
|
||||||
|
// else if (state->data_p_head[slot] == 1 && databurst == 0x06) CRCCorrect = 1;
|
||||||
|
|
||||||
|
//run CRC9 on intermediate and last 1/2 confirmed data blocks
|
||||||
|
else if (state->data_conf_data[slot] == 1 && databurst == 0x7)
|
||||||
|
{
|
||||||
|
blockcounter = state->data_block_counter[slot]; //current block number according to the counter
|
||||||
|
dbsn = (uint32_t)ConvertBitIntoBytes(&BPTCDmrDataBit[0], 7) + 1; //recover data block serial number
|
||||||
|
CRCExtracted = (uint32_t)ConvertBitIntoBytes(&BPTCDmrDataBit[7], 9); //extract CRC from data
|
||||||
|
CRCExtracted = CRCExtracted ^ crcmask;
|
||||||
|
|
||||||
|
//reorganize the BPTCDmrDataBit array into confdatabits, just for CRC9 check
|
||||||
|
//need to find a sample to confirm this
|
||||||
|
for(i = 0; i < 80; i++) confdatabits[i] = BPTCDmrDataBit[i + 16];
|
||||||
|
for(i = 0; i < 7; i++) confdatabits[i + 80] = BPTCDmrDataBit[i];
|
||||||
|
|
||||||
|
CRCComputed = ComputeCrc9Bit(confdatabits, 87);
|
||||||
|
if (CRCExtracted == CRCComputed)
|
||||||
|
{
|
||||||
|
CRCCorrect = 1;
|
||||||
|
state->data_block_crc_valid[slot][blockcounter] = 1;
|
||||||
|
}
|
||||||
|
else state->data_block_crc_valid[slot][blockcounter] = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//run CCITT on other data forms
|
//run CCITT on other data forms
|
||||||
@@ -225,6 +299,20 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
CRCComputed = ComputeCrcCCITT(BPTCDmrDataBit);
|
CRCComputed = ComputeCrcCCITT(BPTCDmrDataBit);
|
||||||
if (CRCComputed == CRCExtracted) CRCCorrect = 1;
|
if (CRCComputed == CRCExtracted) CRCCorrect = 1;
|
||||||
else CRCCorrect = 0;
|
else CRCCorrect = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set the 'RAS Flag', if no irrecoverable errors but bad crc, only when enabled by user (to prevent a lot of bad data CSBKs)
|
||||||
|
if (opts->aggressive_framesync == 0 && CRCCorrect == 0 && IrrecoverableErrors == 0 && BPTCReservedBits == 4) is_ras = 1; //!=0, or == 0x4, or just R[2] == 1
|
||||||
|
|
||||||
|
//make sure the system type isn't Hytera, but could just be bad decodes on bad sample
|
||||||
|
if (BPTCDmrDataByte[1] == 0x68) is_ras = 0;
|
||||||
|
|
||||||
|
//if this is a RAS system, set the CRC to okay if irrecoverable errors is okay
|
||||||
|
//if we don't do this, then we can't view some data (CSBKs on RAS enabled systems)
|
||||||
|
if (is_ras == 1)
|
||||||
|
{
|
||||||
|
crc_original_validity = CRCCorrect;
|
||||||
|
CRCCorrect = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (databurst == 0x04 || databurst == 0x06) //MBC Header, Data Header
|
if (databurst == 0x04 || databurst == 0x06) //MBC Header, Data Header
|
||||||
@@ -295,11 +383,7 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
IrrecoverableErrors = BPTC_128x77_Extract_Data(BptcDataMatrix, LC_DataBit);
|
IrrecoverableErrors = BPTC_128x77_Extract_Data(BptcDataMatrix, LC_DataBit);
|
||||||
|
|
||||||
/* Reconstitute the 5 bit CRC */
|
/* Reconstitute the 5 bit CRC */
|
||||||
CRCExtracted = (LC_DataBit[72] & 1) << 4;
|
CRCExtracted = (uint32_t)ConvertBitIntoBytes(&LC_DataBit[72], 5);
|
||||||
CRCExtracted |= (LC_DataBit[73] & 1) << 3;
|
|
||||||
CRCExtracted |= (LC_DataBit[74] & 1) << 2;
|
|
||||||
CRCExtracted |= (LC_DataBit[75] & 1) << 1;
|
|
||||||
CRCExtracted |= (LC_DataBit[76] & 1) << 0;
|
|
||||||
|
|
||||||
/* Compute the 5 bit CRC */
|
/* Compute the 5 bit CRC */
|
||||||
CRCComputed = ComputeCrc5Bit(LC_DataBit);
|
CRCComputed = ComputeCrc5Bit(LC_DataBit);
|
||||||
@@ -348,6 +432,50 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
DMR_PDU[i] = (uint8_t)TrellisReturn[i+pdu_start];
|
DMR_PDU[i] = (uint8_t)TrellisReturn[i+pdu_start];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(i = 0, j = 0; i < 18; i++, j+=8)
|
||||||
|
{
|
||||||
|
DMR_PDU_bits[j + 0] = (TrellisReturn[i] >> 7) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 1] = (TrellisReturn[i] >> 6) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 2] = (TrellisReturn[i] >> 5) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 3] = (TrellisReturn[i] >> 4) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 4] = (TrellisReturn[i] >> 3) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 5] = (TrellisReturn[i] >> 2) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 6] = (TrellisReturn[i] >> 1) & 0x01;
|
||||||
|
DMR_PDU_bits[j + 7] = (TrellisReturn[i] >> 0) & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set CRC to correct on unconfirmed 3/4 data blocks (for reporting due to no CRC available on these)
|
||||||
|
if (state->data_conf_data[slot] == 0) CRCCorrect = 1;
|
||||||
|
|
||||||
|
//run CRC9 on intermediate and last 3/4 data blocks
|
||||||
|
else if (state->data_conf_data[slot] == 1)
|
||||||
|
{
|
||||||
|
blockcounter = state->data_block_counter[slot]; //current block number according to the counter
|
||||||
|
dbsn = (uint32_t)ConvertBitIntoBytes(&DMR_PDU_bits[0], 7) + 1; //recover data block serial number
|
||||||
|
CRCExtracted = (uint32_t)ConvertBitIntoBytes(&DMR_PDU_bits[7], 9); //extract CRC from data
|
||||||
|
CRCExtracted = CRCExtracted ^ crcmask;
|
||||||
|
|
||||||
|
//reorganize the DMR_PDU_bits array into confdatabits, just for CRC9 check
|
||||||
|
//confirmed working now!
|
||||||
|
for(i = 0; i < 128; i++) confdatabits[i] = DMR_PDU_bits[i + 16];
|
||||||
|
for(i = 0; i < 7; i++) confdatabits[i + 128] = DMR_PDU_bits[i];
|
||||||
|
|
||||||
|
CRCComputed = ComputeCrc9Bit(confdatabits, 135);
|
||||||
|
if (CRCExtracted == CRCComputed)
|
||||||
|
{
|
||||||
|
CRCCorrect = 1;
|
||||||
|
state->data_block_crc_valid[slot][blockcounter] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IrrecoverableErrors = 9; //set as a shim since the trellis decoder is a pain to fix
|
||||||
|
state->data_block_crc_valid[slot][blockcounter] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//reorganize the DMR_PDU_bits into PDU friendly format (minus the dbsn and crc9)
|
||||||
|
memset (DMR_PDU_bits, 0, sizeof(DMR_PDU_bits));
|
||||||
for(i = 0, j = 0; i < pdu_len; i++, j+=8)
|
for(i = 0, j = 0; i < pdu_len; i++, j+=8)
|
||||||
{
|
{
|
||||||
DMR_PDU_bits[j + 0] = (TrellisReturn[i+pdu_start] >> 7) & 0x01;
|
DMR_PDU_bits[j + 0] = (TrellisReturn[i+pdu_start] >> 7) & 0x01;
|
||||||
@@ -360,17 +488,13 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
DMR_PDU_bits[j + 7] = (TrellisReturn[i+pdu_start] >> 0) & 0x01;
|
DMR_PDU_bits[j + 7] = (TrellisReturn[i+pdu_start] >> 0) & 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: run CRC9 on confirmed 3/4 data blocks
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_full) //Rate 1 Data
|
if (is_full) //Rate 1 Data
|
||||||
{
|
{
|
||||||
CRCExtracted = 0;
|
CRCExtracted = 0;
|
||||||
CRCComputed = 0;
|
CRCComputed = 0;
|
||||||
IrrecoverableErrors = 0;
|
IrrecoverableErrors = 0; //implicit, since there is no encoding
|
||||||
|
|
||||||
//TODO: run CRC9 on confirmed data
|
|
||||||
|
|
||||||
for (i = 0; i < 24; i++)
|
for (i = 0; i < 24; i++)
|
||||||
{
|
{
|
||||||
@@ -381,6 +505,32 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
DMR_PDU[25] = (uint8_t)ConvertBitIntoBytes(&info[192], 4);
|
DMR_PDU[25] = (uint8_t)ConvertBitIntoBytes(&info[192], 4);
|
||||||
DMR_PDU[25] = DMR_PDU[25] << 4;
|
DMR_PDU[25] = DMR_PDU[25] << 4;
|
||||||
|
|
||||||
|
//set CRC to correct on unconfirmed 1 rate data blocks (for reporting due to no CRC available on these)
|
||||||
|
if (state->data_conf_data[slot] == 0) CRCCorrect = 1;
|
||||||
|
|
||||||
|
//run CRC9 on intermediate and last 1 rate data blocks
|
||||||
|
else if (state->data_conf_data[slot] == 1)
|
||||||
|
{
|
||||||
|
blockcounter = state->data_block_counter[slot]; //current block number according to the counter
|
||||||
|
dbsn = (uint32_t)ConvertBitIntoBytes(&info[0], 7) + 1; //recover data block serial number
|
||||||
|
CRCExtracted = (uint32_t)ConvertBitIntoBytes(&info[7], 9); //extract CRC from data
|
||||||
|
CRCExtracted = CRCExtracted ^ crcmask;
|
||||||
|
|
||||||
|
//reorganize the info bit array into confdatabits, just for CRC9 check
|
||||||
|
//unconfirmed, haven't seen any samples with rate 1 data
|
||||||
|
for(i = 0; i < 176; i++) confdatabits[i] = info[i + 16];
|
||||||
|
for(i = 0; i < 7; i++) confdatabits[i + 176] = info[i];
|
||||||
|
|
||||||
|
CRCComputed = ComputeCrc9Bit(confdatabits, 183);
|
||||||
|
if (CRCExtracted == CRCComputed)
|
||||||
|
{
|
||||||
|
CRCCorrect = 1;
|
||||||
|
state->data_block_crc_valid[slot][blockcounter] = 1;
|
||||||
|
}
|
||||||
|
else state->data_block_crc_valid[slot][blockcounter] = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//copy info to dmr_pdu_bits
|
//copy info to dmr_pdu_bits
|
||||||
memcpy(DMR_PDU_bits, info, sizeof(DMR_PDU_bits));
|
memcpy(DMR_PDU_bits, info, sizeof(DMR_PDU_bits));
|
||||||
|
|
||||||
@@ -399,13 +549,12 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
if (databurst == 0x06) dmr_dheader (opts, state, DMR_PDU, CRCCorrect, IrrecoverableErrors);
|
if (databurst == 0x06) dmr_dheader (opts, state, DMR_PDU, CRCCorrect, IrrecoverableErrors);
|
||||||
if (databurst == 0x07) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //1/2 Rate Data
|
if (databurst == 0x07) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //1/2 Rate Data
|
||||||
if (databurst == 0x08) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //3/4 Rate Data
|
if (databurst == 0x08) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //3/4 Rate Data
|
||||||
//if (databurst == 0x0A) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //Full Rate Data - Disabled until further testing can be done
|
if (databurst == 0x0A) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //Full Rate Data
|
||||||
|
|
||||||
//is unified data handled like normal data, or control signalling data?
|
//my best understanding is that unified data carries supplimentary MS data on TIII systems, not control signalling
|
||||||
if (databurst == 0x0B) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //Unified Data
|
if (databurst == 0x0B) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 1); //Unified Data
|
||||||
//if (databurst == 0x0B) dmr_cspdu (opts, state, DMR_PDU_bits, DMR_PDU, CRCCorrect, IrrecoverableErrors);
|
|
||||||
|
|
||||||
//control signalling types (CSBK, MBC, UDT)
|
//control signalling types (CSBK, MBC)
|
||||||
if (databurst == 0x03) dmr_cspdu (opts, state, DMR_PDU_bits, DMR_PDU, CRCCorrect, IrrecoverableErrors);
|
if (databurst == 0x03) dmr_cspdu (opts, state, DMR_PDU_bits, DMR_PDU, CRCCorrect, IrrecoverableErrors);
|
||||||
|
|
||||||
//both MBC header and MBC continuation will go to the block_assembler - type 2, and then to dmr_cspdu
|
//both MBC header and MBC continuation will go to the block_assembler - type 2, and then to dmr_cspdu
|
||||||
@@ -416,6 +565,44 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
}
|
}
|
||||||
if (databurst == 0x05) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 2);
|
if (databurst == 0x05) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 2);
|
||||||
|
|
||||||
|
//set the original CRCCorrect back to its original value if the RAS flag was tripped
|
||||||
|
if (is_ras == 1) CRCCorrect = crc_original_validity;
|
||||||
|
|
||||||
|
//start printing relevant fec/crc/ras messages, don't print on idle or MBC continuation blocks (handled in dmr_block.c)
|
||||||
|
if (CRCCorrect == 1 && databurst != 0x09 && databurst != 0x05) ; //fprintf(stderr, "(CRC OK)");
|
||||||
|
|
||||||
|
if (IrrecoverableErrors == 0 && CRCCorrect == 0 && databurst != 0x09 && databurst != 0x05)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KYEL);
|
||||||
|
fprintf(stderr, " (FEC OK)");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IrrecoverableErrors != 0 && databurst != 0x09 && databurst != 0x05)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf(stderr, " (FEC ERR)");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
//print whether or not the 'RAS Field' bits are set to indicate RAS enabled (to be verified)
|
||||||
|
if (is_ras == 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " -RAS ");
|
||||||
|
//the value of this field seems to always, or usually, be 4, or just R[2] bit is set
|
||||||
|
if (opts->payload == 1) fprintf (stderr, "%X ", BPTCReservedBits);
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CRCCorrect == 0 && databurst != 0x09 && databurst != 0x05)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " (CRC ERR) ");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
//print the unified PDU format here, if not slot idle
|
//print the unified PDU format here, if not slot idle
|
||||||
if (opts->payload == 1 && databurst != 0x09)
|
if (opts->payload == 1 && databurst != 0x09)
|
||||||
{
|
{
|
||||||
@@ -427,20 +614,31 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
|||||||
fprintf (stderr, "[%02X]", DMR_PDU[i]);
|
fprintf (stderr, "[%02X]", DMR_PDU[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//debug print
|
||||||
|
// if (dbsn) fprintf (stderr, " SN %X", dbsn);
|
||||||
|
// fprintf (stderr, " CRC - EXT %X CMP %X", CRCExtracted, CRCComputed);
|
||||||
|
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
// fprintf (stderr, "%s", KCYN);
|
//short data - DD_HEAD, SP_HEAD or R_HEAD (Might do on TMS as well)
|
||||||
// fprintf (stderr, "\n Hex to Ascii - ");
|
if ( (state->data_header_format[slot] & 0xF) == 0xD )
|
||||||
// for (i = 0; i < 12; i++)
|
{
|
||||||
// {
|
fprintf (stderr, "%s", KCYN);
|
||||||
// if (DMR_PDU[i] <= 0x7E && DMR_PDU[i] >=0x20)
|
fprintf (stderr, "\n Hex to Ascii - ");
|
||||||
// {
|
for (i = 0; i < pdu_len; i++)
|
||||||
// fprintf (stderr, "%c", DMR_PDU[i]);
|
{
|
||||||
// }
|
if (DMR_PDU[i] <= 0x7E && DMR_PDU[i] >=0x20)
|
||||||
// else fprintf (stderr, ".");
|
{
|
||||||
// }
|
fprintf (stderr, "%c", DMR_PDU[i]);
|
||||||
|
}
|
||||||
|
else fprintf (stderr, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr,"%s", KNRM);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fprintf (stderr,"%s", KNRM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
178
src/dmr_flco.c
178
src/dmr_flco.c
@@ -25,11 +25,13 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
uint8_t so = 0;
|
uint8_t so = 0;
|
||||||
uint32_t target = 0;
|
uint32_t target = 0;
|
||||||
uint32_t source = 0;
|
uint32_t source = 0;
|
||||||
|
uint8_t capsite = 0;
|
||||||
int restchannel = -1;
|
int restchannel = -1;
|
||||||
int is_cap_plus = 0;
|
int is_cap_plus = 0;
|
||||||
int is_alias = 0;
|
int is_alias = 0;
|
||||||
int is_gps = 0;
|
int is_gps = 0;
|
||||||
uint8_t slot = state->currentslot;
|
uint8_t slot = state->currentslot;
|
||||||
|
uint8_t unk = 0; //flag for unknown FLCO + FID combo
|
||||||
|
|
||||||
|
|
||||||
pf = (uint8_t)(lc_bits[0]); //Protect Flag
|
pf = (uint8_t)(lc_bits[0]); //Protect Flag
|
||||||
@@ -40,48 +42,106 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
target = (uint32_t)ConvertBitIntoBytes(&lc_bits[24], 24); //Target or Talk Group
|
target = (uint32_t)ConvertBitIntoBytes(&lc_bits[24], 24); //Target or Talk Group
|
||||||
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[48], 24);
|
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[48], 24);
|
||||||
|
|
||||||
|
//check protect flag
|
||||||
|
if (pf == 1)
|
||||||
|
{
|
||||||
|
if (type == 1) fprintf (stderr, "%s \n", KRED);
|
||||||
|
if (type == 2) fprintf (stderr, "%s \n", KRED);
|
||||||
|
if (type == 3) fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
|
fprintf (stderr, " Protected LC ");
|
||||||
|
goto END_FLCO;
|
||||||
|
}
|
||||||
|
|
||||||
//look for Cap+ on VLC header, then set source and/or rest channel appropriately
|
//look for Cap+ on VLC header, then set source and/or rest channel appropriately
|
||||||
if (type == 1 && fid == 0x10 && flco == 0x04)
|
if (IrrecoverableErrors == 0 && type == 1 && fid == 0x10 && (flco == 0x04 || flco == 0x07) ) //0x07 appears to be a cap+ txi private call
|
||||||
{
|
{
|
||||||
is_cap_plus = 1;
|
is_cap_plus = 1;
|
||||||
restchannel = (int)ConvertBitIntoBytes(&lc_bits[48], 8);
|
capsite = (uint8_t)ConvertBitIntoBytes(&lc_bits[48], 4); //can't verify, just speculating
|
||||||
|
restchannel = (int)ConvertBitIntoBytes(&lc_bits[52], 4); //was 48,8
|
||||||
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[56], 16);
|
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[56], 16);
|
||||||
sprintf (state->dmr_branding, "%s", "Motorola");
|
// sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IrrecoverableErrors == 0)
|
if (IrrecoverableErrors == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (slot == 0) state->dmr_flco = flco;
|
||||||
|
else state->dmr_flcoR = flco;
|
||||||
|
|
||||||
//Embedded Talker Alias Header Only (format and len storage)
|
//Embedded Talker Alias Header Only (format and len storage)
|
||||||
if (type == 3 && flco == 0x04)
|
if (fid == 0 && type == 3 && flco == 0x04)
|
||||||
{
|
{
|
||||||
dmr_embedded_alias_header(opts, state, lc_bits);
|
dmr_embedded_alias_header(opts, state, lc_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Embedded Talker Alias Header (continuation) and Blocks
|
//Embedded Talker Alias Header (continuation) and Blocks
|
||||||
if (type == 3 && flco > 0x3 && flco < 0x08)
|
if (fid == 0 && type == 3 && flco > 0x3 && flco < 0x08)
|
||||||
{
|
{
|
||||||
is_alias = 1;
|
is_alias = 1;
|
||||||
dmr_embedded_alias_blocks(opts, state, lc_bits);
|
dmr_embedded_alias_blocks(opts, state, lc_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Embedded GPS
|
//Embedded GPS
|
||||||
if (type == 3 && flco == 0x08)
|
if (fid == 0 && type == 3 && flco == 0x08)
|
||||||
{
|
{
|
||||||
is_gps = 1;
|
is_gps = 1;
|
||||||
if (fid == 0) dmr_embedded_gps(opts, state, lc_bits); //issues with fid 0x10 and flco 0x08
|
dmr_embedded_gps(opts, state, lc_bits);
|
||||||
|
}
|
||||||
|
|
||||||
//NOTE: fid 0x10 and flco 0x08 produces a lot of 'zero' lat or lon values, I don't believe this is embedded gps
|
//Unknown CapMax/Moto Things
|
||||||
|
if (fid == 0x10 && (flco == 0x08 || flco == 0x28))
|
||||||
|
{
|
||||||
|
//NOTE: fid 0x10 and flco 0x08 (emb) produces a lot of 'zero' bytes
|
||||||
//this has been observed to happen often on CapMax systems, so I believe it could be some CapMax 'thing'
|
//this has been observed to happen often on CapMax systems, so I believe it could be some CapMax 'thing'
|
||||||
//Unknown Link Control - FLCO=0x08 FID=0x10 SVC=0xC1 or FLCO=0x08 FID=0x10 SVC=0xC0 <-- have the enc bit set on svc, but these calls aren't enc?
|
//Unknown Link Control - FLCO=0x08 FID=0x10 SVC=0xC1 or FLCO=0x08 FID=0x10 SVC=0xC0 <- probably no SVC bits in the lc
|
||||||
//is this an encrypted embedded link control?
|
//flco 0x28 has also been observed lately but the tg and src values don't match
|
||||||
else
|
//another flco 0x10 does seem to match, so is probably capmax group call flco
|
||||||
{
|
if (type == 1) fprintf (stderr, "%s \n", KCYN);
|
||||||
fprintf (stderr, "%s", KGRN);
|
if (type == 2) fprintf (stderr, "%s \n", KCYN);
|
||||||
fprintf (stderr, " Slot %d Unknown EMB LC - FLCO=0x%02X FID=0x%02X SVC=0x%02X ", slot+1, flco, fid, so);
|
if (type == 3) fprintf (stderr, "%s", KCYN);
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
}
|
fprintf (stderr, " Motorola");
|
||||||
|
unk = 1;
|
||||||
|
goto END_FLCO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//7.1.1.1 Terminator Data Link Control PDU - ETSI TS 102 361-3 V1.2.1 (2013-07)
|
||||||
|
if (type == 2 && flco == 0x30)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s \n", KRED);
|
||||||
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
|
fprintf (stderr, " Data Terminator (TD_LC)");
|
||||||
|
fprintf (stderr, "%s ", KNRM);
|
||||||
|
goto END_FLCO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Unknown Tait Things
|
||||||
|
if (fid == 0x58)
|
||||||
|
{
|
||||||
|
//NOTE: fid 0x58 (tait) had a single flco 0x06 emb observed, but without the other blocks (4,5,7) for an alias
|
||||||
|
//will need to observe this one, or just remove it from the list, going to isolate tait lc for now
|
||||||
|
if (type == 1) fprintf (stderr, "%s \n", KCYN);
|
||||||
|
if (type == 2) fprintf (stderr, "%s \n", KCYN);
|
||||||
|
if (type == 3) fprintf (stderr, "%s", KCYN);
|
||||||
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
|
fprintf (stderr, " Tait");
|
||||||
|
unk = 1;
|
||||||
|
goto END_FLCO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unknown other manufacturer or OTA ENC, etc.
|
||||||
|
if (fid != 0 && fid != 0x68 && fid != 0x10) //removed tait from the list
|
||||||
|
{
|
||||||
|
if (type == 1) fprintf (stderr, "%s \n", KYEL);
|
||||||
|
if (type == 2) fprintf (stderr, "%s \n", KYEL);
|
||||||
|
if (type == 3) fprintf (stderr, "%s", KYEL);
|
||||||
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
|
fprintf (stderr, " Unknown LC ");
|
||||||
|
unk = 1;
|
||||||
|
goto END_FLCO;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -131,6 +191,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
// state->lastsrc = 0;
|
// state->lastsrc = 0;
|
||||||
state->payload_algid = 0;
|
state->payload_algid = 0;
|
||||||
state->payload_mi = 0;
|
state->payload_mi = 0;
|
||||||
|
state->payload_keyid = 0;
|
||||||
}
|
}
|
||||||
if (state->currentslot == 1)
|
if (state->currentslot == 1)
|
||||||
{
|
{
|
||||||
@@ -140,6 +201,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
// state->lastsrcR = 0;
|
// state->lastsrcR = 0;
|
||||||
state->payload_algidR = 0;
|
state->payload_algidR = 0;
|
||||||
state->payload_miR = 0;
|
state->payload_miR = 0;
|
||||||
|
state->payload_keyidR = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,14 +224,32 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
fprintf(stderr, "TGT=%u SRC=%u ", target, source);
|
fprintf(stderr, "TGT=%u SRC=%u ", target, source);
|
||||||
if (opts->payload == 1) fprintf(stderr, "FLCO=0x%02X FID=0x%02X SVC=0x%02X ", flco, fid, so);
|
if (opts->payload == 1) fprintf(stderr, "FLCO=0x%02X FID=0x%02X SVC=0x%02X ", flco, fid, so);
|
||||||
|
|
||||||
if (flco == 3) //UU_V_Ch_Usr
|
//0x04 and 0x05 on a TLC seem to indicate a Cap + Private Call Terminator (perhaps one for each MS)
|
||||||
|
//0x07 on a VLC seems to indicate a Cap+ Private Call Header
|
||||||
|
//0x23 on the Embedded Voice Burst Sync seems to indicate a Cap+ Private Call in progress
|
||||||
|
if (flco == 0x4 || flco == 0x5 || flco == 0x7 || flco == 0x23) //Cap+ Things
|
||||||
{
|
{
|
||||||
sprintf (state->call_string[slot], " Private");
|
sprintf (state->call_string[slot], " Cap+");
|
||||||
|
fprintf (stderr, "Cap+ ");
|
||||||
|
if (flco == 0x4)
|
||||||
|
{
|
||||||
|
strcat (state->call_string[slot], " Grp");
|
||||||
|
fprintf (stderr, "Group ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcat (state->call_string[slot], " Pri");
|
||||||
|
fprintf (stderr, "Private ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (flco == 0x3) //UU_V_Ch_Usr
|
||||||
|
{
|
||||||
|
sprintf (state->call_string[slot], " Private ");
|
||||||
fprintf (stderr, "Private ");
|
fprintf (stderr, "Private ");
|
||||||
}
|
}
|
||||||
else //Grp_V_Ch_Usr
|
else //Grp_V_Ch_Usr
|
||||||
{
|
{
|
||||||
sprintf (state->call_string[slot], " Group");
|
sprintf (state->call_string[slot], " Group ");
|
||||||
fprintf (stderr, "Group ");
|
fprintf (stderr, "Group ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +286,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
{
|
{
|
||||||
//REMUS! Uncomment Line Below if desired
|
//REMUS! Uncomment Line Below if desired
|
||||||
// strcat (state->call_string[slot], " RES");
|
// strcat (state->call_string[slot], " RES");
|
||||||
fprintf(stderr, "Reserved=%d ", (so & 0x30) >> 4);
|
fprintf(stderr, "RS%d ", (so & 0x30) >> 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(so & 0x08)
|
if(so & 0x08)
|
||||||
@@ -251,10 +331,6 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
|
|
||||||
fprintf(stderr, "Call ");
|
fprintf(stderr, "Call ");
|
||||||
|
|
||||||
fprintf (stderr, "%s", KRED);
|
|
||||||
if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
|
|
||||||
else if(IrrecoverableErrors == 0) fprintf(stderr, "(FEC/RAS)");
|
|
||||||
else fprintf(stderr, "(FEC/CRC ERR)");
|
|
||||||
|
|
||||||
//check Cap+ rest channel info if available and good fec
|
//check Cap+ rest channel info if available and good fec
|
||||||
if (is_cap_plus == 1)
|
if (is_cap_plus == 1)
|
||||||
@@ -299,6 +375,24 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
END_FLCO:
|
||||||
|
if (unk == 1 || pf == 1)
|
||||||
|
{
|
||||||
|
// fprintf(stderr, " FLCO=0x%02X FID=0x%02X SVC=0x%02X ", flco, fid, so);
|
||||||
|
fprintf(stderr, " FLCO=0x%02X FID=0x%02X ", flco, fid); //not all LC PDUs contain SVC bits (see TD_LC)
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IrrecoverableErrors != 0)
|
||||||
|
{
|
||||||
|
if (type != 3) fprintf (stderr, "\n");
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " SLOT %d", state->currentslot+1);
|
||||||
|
fprintf (stderr, " FLCO FEC ERR ");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//externalized dmr cach - tact and slco fragment handling
|
//externalized dmr cach - tact and slco fragment handling
|
||||||
@@ -553,7 +647,9 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
|
|||||||
uint8_t con_netid = (uint8_t)ConvertBitIntoBytes(&slco_bits[8], 8);
|
uint8_t con_netid = (uint8_t)ConvertBitIntoBytes(&slco_bits[8], 8);
|
||||||
uint8_t con_siteid = (uint8_t)ConvertBitIntoBytes(&slco_bits[16], 8);
|
uint8_t con_siteid = (uint8_t)ConvertBitIntoBytes(&slco_bits[16], 8);
|
||||||
//Cap+
|
//Cap+
|
||||||
uint8_t restchannel = (uint8_t)ConvertBitIntoBytes(&slco_bits[12], 8);
|
uint8_t capsite = (uint8_t)ConvertBitIntoBytes(&slco_bits[12], 4); //can't verify, just speculating
|
||||||
|
uint8_t restchannel = (uint8_t)ConvertBitIntoBytes(&slco_bits[16], 4); //was 12,8
|
||||||
|
uint8_t cap_reserved = (uint8_t)ConvertBitIntoBytes(&slco_bits[20], 8); //unknown if any significant value?
|
||||||
|
|
||||||
//initial line break
|
//initial line break
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
@@ -602,18 +698,20 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
|
|||||||
fprintf (stderr, " SLCO Activity Update TS1: %X Hash: %02X TS2: %X Hash: %02X", ts1_act, ts1_hash, ts2_act, ts2_hash); //102 361-2 7.1.3.2
|
fprintf (stderr, " SLCO Activity Update TS1: %X Hash: %02X TS2: %X Hash: %02X", ts1_act, ts1_hash, ts2_act, ts2_hash); //102 361-2 7.1.3.2
|
||||||
else if (slco == 0x9)
|
else if (slco == 0x9)
|
||||||
{
|
{
|
||||||
state->dmr_mfid = 0x10;
|
//remove all setting of branding/sub from SLCO, can cause false positives even with seeming good CRC
|
||||||
sprintf (state->dmr_branding, "%s", "Motorola");
|
|
||||||
sprintf (state->dmr_branding_sub, "%s", "Con+ ");
|
// state->dmr_mfid = 0x10;
|
||||||
|
// sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
|
// sprintf (state->dmr_branding_sub, "%s", "Con+ ");
|
||||||
fprintf (stderr, " SLCO Connect Plus Voice Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
|
fprintf (stderr, " SLCO Connect Plus Voice Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
|
||||||
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
|
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (slco == 0xA)
|
else if (slco == 0xA)
|
||||||
{
|
{
|
||||||
state->dmr_mfid = 0x10;
|
// state->dmr_mfid = 0x10;
|
||||||
sprintf (state->dmr_branding, "%s", "Motorola");
|
// sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
sprintf (state->dmr_branding_sub, "%s", "Con+ ");
|
// sprintf (state->dmr_branding_sub, "%s", "Con+ ");
|
||||||
fprintf (stderr, " SLCO Connect Plus Control Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
|
fprintf (stderr, " SLCO Connect Plus Control Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
|
||||||
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
|
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
|
||||||
|
|
||||||
@@ -627,11 +725,11 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
|
|||||||
|
|
||||||
else if (slco == 0xF)
|
else if (slco == 0xF)
|
||||||
{
|
{
|
||||||
state->dmr_mfid = 0x10;
|
// state->dmr_mfid = 0x10;
|
||||||
sprintf (state->dmr_branding, "%s", "Motorola");
|
// sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
|
||||||
fprintf (stderr, " SLCO Capacity Plus Rest Channel %d", restchannel);
|
fprintf (stderr, " SLCO Capacity Plus Site: %d - Rest Channel %d - RS: %02X", capsite+1, restchannel, cap_reserved);
|
||||||
state->dmr_rest_channel = restchannel;
|
// state->dmr_rest_channel = restchannel; //test without, may work better
|
||||||
//assign to cc freq if available
|
//assign to cc freq if available
|
||||||
if (state->trunk_chan_map[restchannel] != 0)
|
if (state->trunk_chan_map[restchannel] != 0)
|
||||||
{
|
{
|
||||||
@@ -639,7 +737,7 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
|
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
|
||||||
sprintf(state->dmr_site_parms, "%s", "");
|
// sprintf(state->dmr_site_parms, "%s", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
else fprintf (stderr, " SLCO Unknown - %d ", slco);
|
else fprintf (stderr, " SLCO Unknown - %d ", slco);
|
||||||
|
|||||||
154
src/dmr_le.c
154
src/dmr_le.c
@@ -137,3 +137,157 @@ void dmr_alg_reset (dsd_opts * opts, dsd_state * state)
|
|||||||
state->payload_miP = 0;
|
state->payload_miP = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//handle Single Burst (Voice Burst F) or Reverse Channel Signalling
|
||||||
|
//(Embedded or Dedicated Outbound, not Stand Alone (MS sourced) or Direct Mode)
|
||||||
|
//MS Sourced or Direct Mode probably would be handled poorly by the demodulator
|
||||||
|
void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t slot = state->currentslot;
|
||||||
|
uint8_t sbrc_interleaved[32];
|
||||||
|
uint8_t sbrc_return[32];
|
||||||
|
memset (sbrc_interleaved, 0, sizeof(sbrc_interleaved));
|
||||||
|
memset (sbrc_return, 0, sizeof(sbrc_return));
|
||||||
|
uint32_t irr_err = 0;
|
||||||
|
uint32_t sbrc_hex = 0;
|
||||||
|
uint16_t crc_extracted = 7777;
|
||||||
|
uint16_t crc_computed = 9999;
|
||||||
|
uint8_t crc_okay = 0;
|
||||||
|
|
||||||
|
// 9.3.2 Pre-emption and power control Indicator (PI)
|
||||||
|
// 0 - The embedded signalling carries information associated to the same logical channel or the Null embedded message
|
||||||
|
// 1 - The embedded signalling carries RC information associated to the other logical channel
|
||||||
|
|
||||||
|
for(i = 0; i < 32; i++) sbrc_interleaved[i] = state->dmr_embedded_signalling[slot][5][i + 8];
|
||||||
|
//power == 0 should be single burst
|
||||||
|
if (power == 0) irr_err = BPTC_16x2_Extract_Data(sbrc_interleaved, sbrc_return, 0);
|
||||||
|
//power == 1 should be reverse channel -- still need to check the interleave inside of BPTC
|
||||||
|
if (power == 1) irr_err = BPTC_16x2_Extract_Data(sbrc_interleaved, sbrc_return, 1);
|
||||||
|
//bad emb burst, never set a valid power indicator value (probably 9)
|
||||||
|
if (power > 1) goto SBRC_END;
|
||||||
|
|
||||||
|
//RC Channel CRC 7 Mask = 0x7A; CRC bits are used as privacy indicators on
|
||||||
|
//Single Voice Burst F (see below), other moto values seem to exist there as well
|
||||||
|
//unknown what the other values are (see Cap+ 0x313)
|
||||||
|
if (power == 1) //RC
|
||||||
|
{
|
||||||
|
crc_extracted = 0;
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
crc_extracted = crc_extracted << 1;
|
||||||
|
crc_extracted = crc_extracted | sbrc_return[i+4];
|
||||||
|
}
|
||||||
|
crc_extracted = crc_extracted ^ 0x7A;
|
||||||
|
crc_computed = crc7((uint8_t *) sbrc_return, 11);
|
||||||
|
if (crc_extracted == crc_computed) crc_okay = 1;
|
||||||
|
}
|
||||||
|
else crc_okay = 1; //SB
|
||||||
|
|
||||||
|
if (opts->payload == 1) //hide the sb/rc behind the payload printer, won't be useful to most people right now
|
||||||
|
{
|
||||||
|
fprintf (stderr, "\n %s", KCYN);
|
||||||
|
if (power == 0) fprintf (stderr, " SB: ");
|
||||||
|
if (power == 1) fprintf (stderr, " RC: ");
|
||||||
|
for(i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
sbrc_hex = sbrc_hex << 1;
|
||||||
|
sbrc_hex |= sbrc_return[i] & 1; //sbrc_return
|
||||||
|
fprintf (stderr, "%d", sbrc_return[i]);
|
||||||
|
}
|
||||||
|
fprintf (stderr, " - %03X", sbrc_hex);
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
|
if (crc_okay == 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " (CRC ERR)");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
if (opts->payload == 1) fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//sbrc_hex value of 0x313 seems to be some Cap+ Thing,
|
||||||
|
//also observed 0x643 on another cap+ system (site id, status? something?)
|
||||||
|
//I've observed it in the Private Cap+ TXI calls as well
|
||||||
|
//there also seems to be a correlation between the SVC bits for TXI (reserved=3) and these extra cap+ values
|
||||||
|
uint8_t sbrc_opcode = sbrc_hex;
|
||||||
|
uint8_t alg = sbrc_hex & 3;
|
||||||
|
uint16_t key = (sbrc_hex >> 3) & 0xFF;
|
||||||
|
|
||||||
|
if (opts->payload == 1)
|
||||||
|
{
|
||||||
|
if (irr_err != 0) fprintf (stderr, "%s (FEC ERR) %d %s", KRED, irr_err, KNRM);
|
||||||
|
if (irr_err == 0)
|
||||||
|
{
|
||||||
|
if (sbrc_hex == 0) ; //NULL
|
||||||
|
else if (sbrc_hex == 0x313)
|
||||||
|
{
|
||||||
|
//Cap+ Thing? Observed On Cap+ Systems
|
||||||
|
// fprintf (stderr, " Cap+ Thing?");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if (slot == 0)
|
||||||
|
{
|
||||||
|
//key and alg only present SOME times, not all,
|
||||||
|
//also, intermixed with other signalling
|
||||||
|
//needs more study first!
|
||||||
|
if (state->dmr_so & 0x40 && key != 0 && state->payload_keyid == 0)
|
||||||
|
{
|
||||||
|
if (opts->payload == 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s ", KYEL);
|
||||||
|
fprintf (stderr, "\n Slot 1");
|
||||||
|
fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
|
||||||
|
fprintf (stderr, "%s ", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
//needs more study before assignment
|
||||||
|
//state->payload_keyid = key;
|
||||||
|
//state->payload_algid = alg + 0x20; //assuming DMRA approved alg values (moto patent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slot == 1)
|
||||||
|
{
|
||||||
|
if (state->dmr_soR & 0x40 && key != 0 && state->payload_keyidR == 0)
|
||||||
|
{
|
||||||
|
if (opts->payload == 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s ", KYEL);
|
||||||
|
fprintf (stderr, "\n Slot 2");
|
||||||
|
fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key);
|
||||||
|
fprintf (stderr, "%s ", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
//needs more study before assignment
|
||||||
|
//state->payload_keyidR = key;
|
||||||
|
//state->payload_algidR = alg + 0x20; //assuming DMRA approved alg values (moto patent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SBRC_END:
|
||||||
|
|
||||||
|
//'DSP' output to file -- only RC, or RC and SB?
|
||||||
|
if (power == 1 && opts->use_dsp_output == 1 && sbrc_hex != 0) //if not NULL
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 99 ", slot+1); //'99' is RC designation value
|
||||||
|
int k = 0;
|
||||||
|
for (i = 0; i < 24; i++) //12 bytes, SB or RC
|
||||||
|
{
|
||||||
|
//check to see if k++ starts at zero, or at 1
|
||||||
|
int sbrc_nib = (state->dmr_embedded_signalling[slot][5][k++] << 3) | (state->dmr_embedded_signalling[slot][5][k++] << 2) | (state->dmr_embedded_signalling[slot][5][k++] << 1) | (state->dmr_embedded_signalling[slot][5][k++] << 0);
|
||||||
|
fprintf (pFile, "%X", sbrc_nib);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
121
src/dmr_ms.c
121
src/dmr_ms.c
@@ -50,6 +50,11 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
uint8_t internalslot;
|
uint8_t internalslot;
|
||||||
uint8_t vc;
|
uint8_t vc;
|
||||||
|
|
||||||
|
//assign as nonsensical numbers
|
||||||
|
uint8_t cc = 25;
|
||||||
|
uint8_t power = 9; //power and pre-emption indicator
|
||||||
|
uint8_t lcss = 9;
|
||||||
|
|
||||||
//dummy bits to pass to dburst for link control
|
//dummy bits to pass to dburst for link control
|
||||||
uint8_t dummy_bits[196];
|
uint8_t dummy_bits[196];
|
||||||
memset (dummy_bits, 0, sizeof (dummy_bits));
|
memset (dummy_bits, 0, sizeof (dummy_bits));
|
||||||
@@ -87,7 +92,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 12; i++)
|
for(i = 0; i < 12; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
|
|
||||||
cachdata[i] = dibit;
|
cachdata[i] = dibit;
|
||||||
state->dmr_stereo_payload[i] = dibit;
|
state->dmr_stereo_payload[i] = dibit;
|
||||||
@@ -119,7 +124,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 36; i++)
|
for(i = 0; i < 36; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
|
|
||||||
state->dmr_stereo_payload[i+12] = dibit;
|
state->dmr_stereo_payload[i+12] = dibit;
|
||||||
|
|
||||||
@@ -144,7 +149,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 18; i++)
|
for(i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
|
|
||||||
state->dmr_stereo_payload[i+48] = dibit;
|
state->dmr_stereo_payload[i+48] = dibit;
|
||||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
@@ -171,7 +176,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
sync[i] = (dibit | 1) + 48;
|
sync[i] = (dibit | 1) + 48;
|
||||||
|
|
||||||
// load the superframe to do embedded signal processing
|
// load the superframe to do embedded signal processing
|
||||||
if(vc > 1 && vc < 6) //grab on vc1 values 2-5 B C D and E
|
if(vc > 1) //grab on vc1 values 2-5 B C D and E
|
||||||
{
|
{
|
||||||
state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1
|
||||||
state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0
|
state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0
|
||||||
@@ -180,17 +185,41 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sync[24] = 0;
|
sync[24] = 0;
|
||||||
|
|
||||||
|
//test for RC sync pattern in MS sourced audio
|
||||||
|
if ( strcmp (sync, DMR_RC_DATA_SYNC) == 0)
|
||||||
|
{
|
||||||
|
state->dmr_ms_rc = 1;
|
||||||
|
fprintf (stderr, "%s ", getTime());
|
||||||
|
if (opts->inverted_dmr == 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr,"Sync: +DMR MS/DM MODE/MONO ");
|
||||||
|
}
|
||||||
|
else fprintf (stderr,"Sync: -DMR MS/DM MODE/MONO ");
|
||||||
|
|
||||||
|
fprintf (stderr, "| RC ");
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < 8; i++) EmbeddedSignalling[i] = syncdata[i];
|
||||||
|
for(i = 0; i < 8; i++) EmbeddedSignalling[i + 8] = syncdata[i + 40];
|
||||||
|
|
||||||
EmbeddedSignallingOk = -1;
|
EmbeddedSignallingOk = -1;
|
||||||
if(QR_16_7_6_decode(EmbeddedSignalling))
|
if(QR_16_7_6_decode(EmbeddedSignalling))
|
||||||
{
|
{
|
||||||
EmbeddedSignallingOk = 1;
|
EmbeddedSignallingOk = 1;
|
||||||
|
cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]);
|
||||||
|
power = EmbeddedSignalling[4];
|
||||||
|
lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
|
//Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling
|
||||||
for(i = 0; i < 18; i++)
|
for(i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
|
|
||||||
state->dmr_stereo_payload[i+90] = dibit;
|
state->dmr_stereo_payload[i+90] = dibit;
|
||||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
@@ -214,7 +243,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
for(i = 0; i < 36; i++)
|
for(i = 0; i < 36; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
|
|
||||||
state->dmr_stereo_payload[i+108] = dibit;
|
state->dmr_stereo_payload[i+108] = dibit;
|
||||||
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
@@ -227,6 +256,20 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//'DSP' output to file
|
||||||
|
if (opts->use_dsp_output == 1)
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 10 ", state->currentslot+1); //0x10 for "voice burst", forced to slot 1
|
||||||
|
for (i = 6; i < 72; i++) //33 bytes, no CACH
|
||||||
|
{
|
||||||
|
int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", dsp_byte);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
|
|
||||||
state->dmr_ms_mode = 1;
|
state->dmr_ms_mode = 1;
|
||||||
|
|
||||||
memcpy (ambe_fr4, ambe_fr2, sizeof(ambe_fr2));
|
memcpy (ambe_fr4, ambe_fr2, sizeof(ambe_fr2));
|
||||||
@@ -238,22 +281,28 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
memcpy (m2, ambe_fr2, sizeof(m2));
|
memcpy (m2, ambe_fr2, sizeof(m2));
|
||||||
memcpy (m3, ambe_fr3, sizeof(m3));
|
memcpy (m3, ambe_fr3, sizeof(m3));
|
||||||
|
|
||||||
if (state->directmode == 0)
|
if (state->dmr_ms_rc == 0)
|
||||||
{
|
{
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
if (state->directmode == 0)
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
{
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||||
}
|
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||||
else
|
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||||
{
|
}
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr4, NULL); //play duplicate of 2 here to smooth audio on tdma direct
|
else
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
{
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
processMbeFrame (opts, state, NULL, ambe_fr4, NULL); //play duplicate of 2 here to smooth audio on tdma direct
|
||||||
|
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
||||||
|
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vc == 6)
|
if (vc == 6)
|
||||||
{
|
{
|
||||||
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB);
|
||||||
|
//check the single burst/reverse channel opportunity
|
||||||
|
dmr_sbrc (opts, state, power);
|
||||||
|
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
dmr_alg_refresh (opts, state);
|
dmr_alg_refresh (opts, state);
|
||||||
}
|
}
|
||||||
@@ -268,6 +317,12 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
state->last_vc_sync_time = time(NULL);
|
state->last_vc_sync_time = time(NULL);
|
||||||
|
|
||||||
vc++;
|
vc++;
|
||||||
|
|
||||||
|
//reset emb components
|
||||||
|
cc = 25;
|
||||||
|
power = 9; //power and pre-emption indicator
|
||||||
|
lcss = 9;
|
||||||
|
|
||||||
//this is necessary because we need to skip and collect dibits, not just skip them
|
//this is necessary because we need to skip and collect dibits, not just skip them
|
||||||
if (vc > 6) goto END;
|
if (vc > 6) goto END;
|
||||||
|
|
||||||
@@ -292,7 +347,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if (opts->inverted_dmr == 1)
|
if (opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
state->dmr_stereo_payload[i] = dibit;
|
state->dmr_stereo_payload[i] = dibit;
|
||||||
|
|
||||||
@@ -379,7 +434,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = state->dmr_stereo_payload[i];
|
dibit = state->dmr_stereo_payload[i];
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
cachdata[i] = dibit;
|
cachdata[i] = dibit;
|
||||||
}
|
}
|
||||||
@@ -398,7 +453,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = state->dmr_stereo_payload[i+12];
|
dibit = state->dmr_stereo_payload[i+12];
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
state->dmr_stereo_payload[i+12] = dibit;
|
state->dmr_stereo_payload[i+12] = dibit;
|
||||||
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
@@ -425,7 +480,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = state->dmr_stereo_payload[i+48];
|
dibit = state->dmr_stereo_payload[i+48];
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
||||||
@@ -443,8 +498,9 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
|
state->dmr_stereo_payload[i+90] = dibit;
|
||||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
@@ -469,8 +525,9 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1)
|
if(opts->inverted_dmr == 1)
|
||||||
{
|
{
|
||||||
dibit = (dibit ^ 2);
|
dibit = (dibit ^ 2) & 3;
|
||||||
}
|
}
|
||||||
|
state->dmr_stereo_payload[i+108] = dibit;
|
||||||
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||||
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
|
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
@@ -481,6 +538,20 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//'DSP' output to file
|
||||||
|
if (opts->use_dsp_output == 1)
|
||||||
|
{
|
||||||
|
FILE * pFile; //file pointer
|
||||||
|
pFile = fopen (opts->dsp_out_file, "a");
|
||||||
|
fprintf (pFile, "\n%d 10 ", state->currentslot+1); //0x10 for "voice burst", force to slot 1
|
||||||
|
for (i = 6; i < 72; i++) //33 bytes, no CACH
|
||||||
|
{
|
||||||
|
int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1];
|
||||||
|
fprintf (pFile, "%X", dsp_byte);
|
||||||
|
}
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (stderr, "%s ", getTime());
|
fprintf (stderr, "%s ", getTime());
|
||||||
if (opts->inverted_dmr == 0)
|
if (opts->inverted_dmr == 0)
|
||||||
{
|
{
|
||||||
@@ -517,7 +588,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//collect the mi fragment
|
//collect the mi fragment
|
||||||
dmr_late_entry_mi_fragment (opts, state, 1, ambe_fr, ambe_fr2, ambe_fr3);
|
dmr_late_entry_mi_fragment (opts, state, 1, m1, m2, m3);
|
||||||
|
|
||||||
//errors due to skipping other slot
|
//errors due to skipping other slot
|
||||||
// cach_err = dmr_cach (opts, state, cachdata);
|
// cach_err = dmr_cach (opts, state, cachdata);
|
||||||
@@ -558,7 +629,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
dibit = *dibit_p;
|
dibit = *dibit_p;
|
||||||
dibit_p++;
|
dibit_p++;
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
state->dmr_stereo_payload[i] = dibit;
|
state->dmr_stereo_payload[i] = dibit;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -566,7 +637,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state)
|
|||||||
for (i = 0; i < 54; i++)
|
for (i = 0; i < 54; i++)
|
||||||
{
|
{
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2);
|
if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3;
|
||||||
state->dmr_stereo_payload[i+90] = dibit;
|
state->dmr_stereo_payload[i+90] = dibit;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ void dmr_pdu (dsd_opts * opts, dsd_state * state, uint8_t block_len, uint8_t DMR
|
|||||||
//maybe one day we will have more things to do here
|
//maybe one day we will have more things to do here
|
||||||
state->data_conf_data[slot] = 0; //flag off confirmed data after processing it
|
state->data_conf_data[slot] = 0; //flag off confirmed data after processing it
|
||||||
state->data_p_head[slot] = 0; //flag off prop_head data after processing it
|
state->data_p_head[slot] = 0; //flag off prop_head data after processing it
|
||||||
|
state->data_header_format[slot] = 0; //zero out so we don't keep ascii printing
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
src/dmr_pi.c
23
src/dmr_pi.c
@@ -29,7 +29,7 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
|
|||||||
{
|
{
|
||||||
fprintf (stderr, "%s ", KYEL);
|
fprintf (stderr, "%s ", KYEL);
|
||||||
fprintf (stderr, "\n Slot 1");
|
fprintf (stderr, "\n Slot 1");
|
||||||
fprintf (stderr, " DMR PI Header ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algid, state->payload_keyid, state->payload_mi);
|
fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algid, state->payload_keyid, state->payload_mi);
|
||||||
fprintf (stderr, "%s ", KNRM);
|
fprintf (stderr, "%s ", KNRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
|
|||||||
{
|
{
|
||||||
fprintf (stderr, "%s ", KYEL);
|
fprintf (stderr, "%s ", KYEL);
|
||||||
fprintf (stderr, "\n Slot 2");
|
fprintf (stderr, "\n Slot 2");
|
||||||
fprintf (stderr, " DMR PI Header ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algidR, state->payload_keyidR, state->payload_miR);
|
fprintf (stderr, " DMR PI H- ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algidR, state->payload_keyidR, state->payload_miR);
|
||||||
fprintf (stderr, "%s ", KNRM);
|
fprintf (stderr, "%s ", KNRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,21 +73,6 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if((IrrecoverableErrors == 0) && CRCCorrect)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, " (PI CRC Okay)");
|
|
||||||
}
|
|
||||||
else if((IrrecoverableErrors == 0))
|
|
||||||
{
|
|
||||||
//fprintf (stderr, " (PI FEC Okay)");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf (stderr, "%s", KRED);
|
|
||||||
fprintf (stderr, (" (PI FEC ERR)"));
|
|
||||||
fprintf (stderr, "%s ", KNRM);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LFSR(dsd_state * state)
|
void LFSR(dsd_state * state)
|
||||||
@@ -114,7 +99,7 @@ void LFSR(dsd_state * state)
|
|||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
fprintf (stderr, " Slot 1");
|
fprintf (stderr, " Slot 1");
|
||||||
fprintf (stderr, " DMR PI Continuation ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
|
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
|
||||||
fprintf(stderr, " Next MI: 0x%08X", lfsr);
|
fprintf(stderr, " Next MI: 0x%08X", lfsr);
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
@@ -127,7 +112,7 @@ void LFSR(dsd_state * state)
|
|||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
fprintf (stderr, " Slot 2");
|
fprintf (stderr, " Slot 2");
|
||||||
fprintf (stderr, " DMR PI Continuation ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR);
|
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR);
|
||||||
fprintf(stderr, " Next MI: 0x%08X", lfsr);
|
fprintf(stderr, " Next MI: 0x%08X", lfsr);
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
|
|||||||
112
src/dmr_utils.c
112
src/dmr_utils.c
@@ -4,7 +4,7 @@
|
|||||||
//Original Source - https://github.com/LouisErigHerve/dsd
|
//Original Source - https://github.com/LouisErigHerve/dsd
|
||||||
|
|
||||||
//Additional Functions
|
//Additional Functions
|
||||||
//Hamming17123, crc8, crc8ok functions
|
//Hamming17123, crc7, crc8, crc8ok functions
|
||||||
//Original Souce - https://github.com/boatbod/op25
|
//Original Souce - https://github.com/boatbod/op25
|
||||||
|
|
||||||
#include "dsd.h"
|
#include "dsd.h"
|
||||||
@@ -121,6 +121,31 @@ bool crc8_ok(uint8_t bits[], unsigned int len)
|
|||||||
return (crc == crc8(bits,len));
|
return (crc == crc8(bits,len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t crc7(uint8_t bits[], unsigned int len)
|
||||||
|
{
|
||||||
|
uint8_t crc=0;
|
||||||
|
unsigned int K = 7;
|
||||||
|
//G7(x) = x7 + x5 + x2 + x + 1 check poly below for correct (dmr rc crc7)
|
||||||
|
uint8_t poly[8] = {1,0,1,0,0,1,1,1}; // crc7 poly
|
||||||
|
uint8_t buf[256];
|
||||||
|
if (len+K > sizeof(buf)) {
|
||||||
|
// fprintf (stderr, "crc8: buffer length %u exceeds maximum %lu\n", len+K, sizeof(buf));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset (buf, 0, sizeof(buf));
|
||||||
|
for (unsigned int i=0; i<len; i++){
|
||||||
|
buf[i] = bits[i];
|
||||||
|
}
|
||||||
|
for (unsigned int i=0; i<len; i++)
|
||||||
|
if (buf[i])
|
||||||
|
for (unsigned int j=0; j<K+1; j++)
|
||||||
|
buf[i+j] ^= poly[j];
|
||||||
|
for (unsigned int i=0; i<K; i++){
|
||||||
|
crc = (crc << 1) + buf[len + i];
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief : This function compute the CRC-CCITT of the DMR data
|
* @brief : This function compute the CRC-CCITT of the DMR data
|
||||||
* by using the polynomial x^16 + x^12 + x^5 + 1
|
* by using the polynomial x^16 + x^12 + x^5 + 1
|
||||||
@@ -329,4 +354,87 @@ uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength)
|
|||||||
* Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes)
|
* Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes)
|
||||||
*
|
*
|
||||||
* @return The 9 bit CRC
|
* @return The 9 bit CRC
|
||||||
*/
|
*/
|
||||||
|
uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint16_t CRC = 0x0000; /* Initialization value = 0x0000 */
|
||||||
|
/* Polynomial x^9 + x^6 + x^4 + x^3 + 1
|
||||||
|
* Normal = 0x059
|
||||||
|
* Reciprocal = 0x134
|
||||||
|
* Reversed reciprocal = 0x12C */
|
||||||
|
uint16_t Polynome = 0x059;
|
||||||
|
for(i = 0; i < NbData; i++)
|
||||||
|
{
|
||||||
|
if(((CRC >> 8) & 1) ^ (DMRData[i] & 1))
|
||||||
|
{
|
||||||
|
CRC = (CRC << 1) ^ Polynome;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CRC <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Conserve only the 9 LSBs */
|
||||||
|
CRC &= 0x01FF;
|
||||||
|
|
||||||
|
/* Invert the CRC */
|
||||||
|
CRC ^= 0x01FF;
|
||||||
|
|
||||||
|
/* Return the CRC */
|
||||||
|
return CRC;
|
||||||
|
} /* End ComputeCrc9Bit() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief : This function compute the CRC-32 of the DMR data
|
||||||
|
* by using the polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
|
||||||
|
*
|
||||||
|
* @param Input : A buffer pointer of the DMR data (80 bytes)
|
||||||
|
* Rate 1/2 coded confirmed (10 data octets): 80 bit sequence (80 bytes)
|
||||||
|
* Rate 3/4 coded confirmed (16 data octets): 128 bit sequence (120 bytes)
|
||||||
|
* Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes)
|
||||||
|
*
|
||||||
|
* @param NbData : The number of bit to compute
|
||||||
|
* Rate 1/2 coded confirmed (10 data octets): 80 bit sequence (80 bytes)
|
||||||
|
* Rate 3/4 coded confirmed (16 data octets): 128 bit sequence (120 bytes)
|
||||||
|
* Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes)
|
||||||
|
*
|
||||||
|
* @return The 32 bit CRC
|
||||||
|
*/
|
||||||
|
uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t CRC = 0x00000000; /* Initialization value = 0x00000000 */
|
||||||
|
/* Polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
|
||||||
|
* Normal = 0x04C11DB7
|
||||||
|
* Reversed = 0xEDB88320
|
||||||
|
* Reciprocal = 0xDB710641
|
||||||
|
* Reversed reciprocal = 0x82608EDB */
|
||||||
|
uint32_t Polynome = 0x04C11DB7;
|
||||||
|
for(i = 0; i < NbData; i++)
|
||||||
|
{
|
||||||
|
if(((CRC >> 31) & 1) ^ (DMRData[i] & 1))
|
||||||
|
{
|
||||||
|
CRC = (CRC << 1) ^ Polynome;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CRC <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//for whatever reason, we get the CRC returned in a reversed byte order (MSO LSO b***s***)
|
||||||
|
uint32_t a, b, c, d;
|
||||||
|
a = b = c = d = 0;
|
||||||
|
a = (CRC & 0xFF) << 24;
|
||||||
|
b = (CRC & 0xFF00) >> 8;
|
||||||
|
b = b << 16;
|
||||||
|
c = (CRC & 0xFF0000) >> 16;
|
||||||
|
c = c << 8;
|
||||||
|
d = (CRC & 0xFF000000) >> 24;
|
||||||
|
|
||||||
|
CRC = a + b + c + d;
|
||||||
|
/* Return the CRC */
|
||||||
|
return CRC;
|
||||||
|
} /* End ComputeCrc32Bit() */
|
||||||
|
|||||||
261
src/dpmr_voice.c
261
src/dpmr_voice.c
@@ -24,11 +24,18 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
uint8_t CCH[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
uint8_t CCH[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
||||||
uint8_t CCHDescrambled[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
uint8_t CCHDescrambled[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
||||||
uint8_t CCHDeInterleaved[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
uint8_t CCHDeInterleaved[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
||||||
uint8_t CCHDataHammingCorrected[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][48] = {0};
|
uint8_t CCHDataHammingCorrected[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][48];
|
||||||
uint8_t CCHDataCRC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
uint8_t CCHDataCRC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
||||||
uint8_t CCHDataCRCComputed[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
|
||||||
|
memset (CCHDataHammingCorrected, 1, sizeof(CCHDataHammingCorrected));
|
||||||
|
memset (CCHDataCRC, 1, sizeof(CCHDataCRC));
|
||||||
|
|
||||||
|
uint8_t CCHDataCRCComputed[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
||||||
|
memset (CCHDataCRCComputed, 0, sizeof(CCHDataCRCComputed));
|
||||||
|
|
||||||
uint8_t CC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE / 2][24] = {0};
|
uint8_t CC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE / 2][24] = {0};
|
||||||
char ambe_fr[NB_OF_DPMR_VOICE_FRAME_TO_DECODE * 4][4][24] = {0};
|
char ambe_fr[NB_OF_DPMR_VOICE_FRAME_TO_DECODE * 4][4][24];
|
||||||
|
memset (ambe_fr, 0, sizeof (ambe_fr));
|
||||||
const int *w, *x, *y, *z;
|
const int *w, *x, *y, *z;
|
||||||
uint32_t ScramblerLFSR = 0;
|
uint32_t ScramblerLFSR = 0;
|
||||||
bool correctable = true;
|
bool correctable = true;
|
||||||
@@ -56,11 +63,6 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
uint8_t CalledID[8] = {0};
|
uint8_t CalledID[8] = {0};
|
||||||
uint8_t CallingID[8] = {0};
|
uint8_t CallingID[8] = {0};
|
||||||
|
|
||||||
if (opts->errorbars == 1)
|
|
||||||
{
|
|
||||||
//fprintf(stderr, "VOICE e:");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First CCH (Control CHannel) - 72 bit */
|
/* First CCH (Control CHannel) - 72 bit */
|
||||||
k = 0;
|
k = 0;
|
||||||
|
|
||||||
@@ -76,7 +78,6 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
CCH[0][(i * 2)] = (1 & (dibit >> 1)); // bit 1
|
CCH[0][(i * 2)] = (1 & (dibit >> 1)); // bit 1
|
||||||
CCH[0][(i * 2) + 1] = (1 & dibit); // bit 0
|
CCH[0][(i * 2) + 1] = (1 & dibit); // bit 0
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
||||||
@@ -148,9 +149,6 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
||||||
|
|
||||||
//Sync issues occur when FS2 occurs immediatly after the 4th rep, so cutting of 4 early to gain constant resync
|
|
||||||
//probably can't resync fast enough when the next sync starts immediately after the 4th rep of 36 dibits
|
|
||||||
//consider writing a method that will loop this entire process based on the frame numbering found inside the CCH info, is that possible?
|
|
||||||
k = 0;
|
k = 0;
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
@@ -177,16 +175,10 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
x++;
|
x++;
|
||||||
y++;
|
y++;
|
||||||
z++;
|
z++;
|
||||||
//should be fixed now with the frame_sync t_max setup
|
|
||||||
//no more early breaking required
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the Hamming (12,8) error code detection
|
|
||||||
* Not needed because it has already been done
|
|
||||||
* in the "InitAllFecFunction()" function */
|
|
||||||
//Hamming_12_8_init();
|
|
||||||
|
|
||||||
/* Decoding all CCH (Control CHannel) */
|
/* Decoding all CCH (Control CHannel) */
|
||||||
for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++)
|
for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++)
|
||||||
{
|
{
|
||||||
@@ -207,22 +199,8 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
if(HammingCorrectable[i][j] == false) correctable = false;
|
if(HammingCorrectable[i][j] == false) correctable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(correctable)
|
if(correctable) HammingOk[i] = 1;
|
||||||
{
|
else HammingOk[i] = 0;
|
||||||
|
|
||||||
//fprintf(stderr, "CCH data corrected successfully\n");
|
|
||||||
|
|
||||||
|
|
||||||
HammingOk[i] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
//fprintf(stderr, "ERROR !!! CCH data contains uncorrectable bit\n");
|
|
||||||
|
|
||||||
|
|
||||||
HammingOk[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reconstitute the 7 bit CRC */
|
/* Reconstitute the 7 bit CRC */
|
||||||
CCHDataCRC[i] = 0;
|
CCHDataCRC[i] = 0;
|
||||||
@@ -237,24 +215,8 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
/* Compute the 7 bit CRC */
|
/* Compute the 7 bit CRC */
|
||||||
CCHDataCRCComputed[i] = CRC7BitdPMR(CCHDataHammingCorrected[i], 41);
|
CCHDataCRCComputed[i] = CRC7BitdPMR(CCHDataHammingCorrected[i], 41);
|
||||||
|
|
||||||
if(CCHDataCRC[i] == CCHDataCRCComputed[i])
|
if(CCHDataCRC[i] == CCHDataCRCComputed[i]) CrcOk[i] = 1;
|
||||||
{
|
else CrcOk[i] = 0;
|
||||||
|
|
||||||
//fprintf(stderr, "Good CCH CRCs ! CRC received = 0x%02X, CRC computed = 0x%02X\n",
|
|
||||||
// CCHDataCRC[i], CCHDataCRCComputed[i]);
|
|
||||||
|
|
||||||
|
|
||||||
CrcOk[i] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
//fprintf(stderr, "ERROR !!! CCH CRCs are different ! CRC received = 0x%02X, CRC computed = 0x%02X\n",
|
|
||||||
// CCHDataCRC[i], CCHDataCRCComputed[i]);
|
|
||||||
|
|
||||||
|
|
||||||
CrcOk[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill the frame number */
|
/* Fill the frame number */
|
||||||
CCH_FrameNumber[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][0], 2);
|
CCH_FrameNumber[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][0], 2);
|
||||||
@@ -300,45 +262,18 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
CallingID[7] = '\0';
|
CallingID[7] = '\0';
|
||||||
|
|
||||||
|
|
||||||
/* Print Hamming debug info */
|
|
||||||
//fprintf(stderr, " | ");
|
|
||||||
for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++)
|
|
||||||
{
|
|
||||||
//fprintf(stderr, "Hamming[%u]=", i);
|
|
||||||
for(j = 0; j < 6; j++)
|
|
||||||
{
|
|
||||||
//if(HammingCorrectable[i][j]) fprintf(stderr, "1");
|
|
||||||
//else fprintf(stderr, "0");
|
|
||||||
}
|
|
||||||
//fprintf(stderr, " HammingOk[%u]=%u", i, HammingOk[i]);
|
|
||||||
//fprintf(stderr, " CrcOk[%u]=%u", i, CrcOk[i]);
|
|
||||||
//fprintf(stderr, " Bit[%u]=", i);
|
|
||||||
//for(j = 0; j < 7; j++)
|
|
||||||
//{
|
|
||||||
// if(CCHDataHammingCorrected[i][j + 41]) fprintf(stderr, "1");
|
|
||||||
// else fprintf(stderr, "0");
|
|
||||||
//}
|
|
||||||
//fprintf(stderr, " CRCrec=0x%02X CRCcomp=0x%02X", CCHDataCRC[i], CCHDataCRCComputed[i]);
|
|
||||||
//if(i < (NB_OF_DPMR_VOICE_FRAME_TO_DECODE - 1)) fprintf(stderr, " - ");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if (NB_OF_DPMR_VOICE_FRAME_TO_DECODE == 2)
|
|
||||||
/* To determine the part of the payload frame, we need to check the
|
/* To determine the part of the payload frame, we need to check the
|
||||||
* Hamming code result, the CRC and the frame number */
|
* Hamming code result, the CRC and the frame number */
|
||||||
|
|
||||||
// if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 0)) ||
|
// if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 0)) ||
|
||||||
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 1)))
|
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 1)))
|
||||||
|
|
||||||
if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 0)) ||
|
if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 0)) ||
|
||||||
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 1)))
|
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 1)))
|
||||||
{
|
{
|
||||||
/* First part of the super frame */
|
/* First part of the super frame */
|
||||||
PartOfSuperFrame = 1;
|
PartOfSuperFrame = 1;
|
||||||
|
|
||||||
|
|
||||||
//fprintf(stderr, "\nFirst part of the Super Frame");
|
|
||||||
|
|
||||||
|
|
||||||
/* The next part will normally be the second part */
|
/* The next part will normally be the second part */
|
||||||
opts->dPMR_next_part_of_superframe = 2;
|
opts->dPMR_next_part_of_superframe = 2;
|
||||||
|
|
||||||
@@ -366,20 +301,19 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
/* BUGFIX : Copy in all case the TG ID */
|
/* BUGFIX : Copy in all case the TG ID */
|
||||||
strcpy((char *)state->dPMRVoiceFS2Frame.CalledID, (char *)CalledID);
|
strcpy((char *)state->dPMRVoiceFS2Frame.CalledID, (char *)CalledID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To determine the part of the payload frame, we need to check the
|
/* To determine the part of the payload frame, we need to check the
|
||||||
* Hamming code result, the CRC and the frame number */
|
* Hamming code result, the CRC and the frame number */
|
||||||
|
|
||||||
// else if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 2)) ||
|
// else if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 2)) ||
|
||||||
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 3)))
|
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 3)))
|
||||||
|
|
||||||
else if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 2)) ||
|
else if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 2)) ||
|
||||||
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 3)))
|
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 3)))
|
||||||
{
|
{
|
||||||
/* Second part of the super frame */
|
/* Second part of the super frame */
|
||||||
PartOfSuperFrame = 2;
|
PartOfSuperFrame = 2;
|
||||||
|
|
||||||
|
|
||||||
//fprintf(stderr, "\nSecond part of the Super Frame");
|
|
||||||
|
|
||||||
|
|
||||||
/* The next part will normally be the first part */
|
/* The next part will normally be the first part */
|
||||||
opts->dPMR_next_part_of_superframe = 1;
|
opts->dPMR_next_part_of_superframe = 1;
|
||||||
|
|
||||||
@@ -392,7 +326,9 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
CallingID[7] = '\0';
|
CallingID[7] = '\0';
|
||||||
|
|
||||||
/* Determine if the calling SRC ID is correct */
|
/* Determine if the calling SRC ID is correct */
|
||||||
|
|
||||||
//if(HammingOk[0] && CrcOk[0] && HammingOk[1] && CrcOk[1])
|
//if(HammingOk[0] && CrcOk[0] && HammingOk[1] && CrcOk[1])
|
||||||
|
|
||||||
if((CrcOk[0] || (HammingCorrectable[0][0] && HammingCorrectable[0][1])) &&
|
if((CrcOk[0] || (HammingCorrectable[0][0] && HammingCorrectable[0][1])) &&
|
||||||
(CrcOk[1] || (HammingCorrectable[1][0] && HammingCorrectable[1][1])))
|
(CrcOk[1] || (HammingCorrectable[1][0] && HammingCorrectable[1][1])))
|
||||||
{
|
{
|
||||||
@@ -420,132 +356,143 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|||||||
/* Set the next part of the superframe to receive */
|
/* Set the next part of the superframe to receive */
|
||||||
if(opts->dPMR_next_part_of_superframe == 1)
|
if(opts->dPMR_next_part_of_superframe == 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//fprintf(stderr, "Supposed first part of the Super Frame\n");
|
|
||||||
|
|
||||||
|
|
||||||
/* Set the next part as the second part */
|
/* Set the next part as the second part */
|
||||||
opts->dPMR_next_part_of_superframe = 2;
|
opts->dPMR_next_part_of_superframe = 2;
|
||||||
}
|
}
|
||||||
else if(opts->dPMR_next_part_of_superframe == 2)
|
else if(opts->dPMR_next_part_of_superframe == 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
//fprintf(stderr, "Supposed second part of the Super Frame\n");
|
|
||||||
|
|
||||||
|
|
||||||
/* Set the next part as the first part */
|
/* Set the next part as the first part */
|
||||||
opts->dPMR_next_part_of_superframe = 1;
|
opts->dPMR_next_part_of_superframe = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//fprintf(stderr, "Unknown part of the Super Frame\n");
|
|
||||||
|
|
||||||
|
|
||||||
/* Unknown current part, set to 0 */
|
/* Unknown current part, set to 0 */
|
||||||
opts->dPMR_next_part_of_superframe = 0;
|
opts->dPMR_next_part_of_superframe = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1))
|
|
||||||
{
|
|
||||||
//only print the CC and src/tg info if CRC is good
|
|
||||||
/* Display the color code */
|
|
||||||
//fprintf(stderr, " | Color Code=%02d ", (int)state->dPMRVoiceFS2Frame.ColorCode[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Unknown color code, display "??" */
|
|
||||||
//fprintf(stderr, " | Color Code=?? ");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display the destination ID (talk group - TG) */
|
/* Display the destination ID (talk group - TG) */
|
||||||
//fprintf(stderr, "| TG=%s", CalledID);
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
if(state->dPMRVoiceFS2Frame.CalledIDOk)
|
if(state->dPMRVoiceFS2Frame.CalledIDOk)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KGRN);
|
fprintf (stderr, "%s", KGRN);
|
||||||
fprintf(stderr, "\n| TG=%s", CalledID);
|
fprintf(stderr, " TG=%s", CalledID);
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
//strcpy (state->dpmr_target_id, CalledID); //HERE HERE
|
|
||||||
state->dpmr_target_id = CalledID;
|
//check other as well before assigning
|
||||||
//fprintf(stderr, " (CRC OK) ");
|
if(state->dPMRVoiceFS2Frame.CallingIDOk) sprintf (state->dpmr_target_id, "%s", CalledID);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf(stderr, " TG=(CRC ERR)");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display the source ID */
|
||||||
|
if(state->dPMRVoiceFS2Frame.CallingIDOk)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KGRN);
|
||||||
|
fprintf(stderr, " Src=%s", CallingID);
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
|
||||||
|
//check other as well before assigning
|
||||||
|
if(state->dPMRVoiceFS2Frame.CalledIDOk) sprintf (state->dpmr_caller_id, "%s", CallingID);
|
||||||
|
|
||||||
|
//stashed channel code in here, more likely to be correct, but no guarantee
|
||||||
if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1))
|
if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1))
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KGRN);
|
fprintf (stderr, "%s", KGRN);
|
||||||
fprintf(stderr, " | Color Code=%02d ", (int)state->dPMRVoiceFS2Frame.ColorCode[0]);
|
fprintf(stderr, " Channel Code=%02d", (int)state->dPMRVoiceFS2Frame.ColorCode[0]);
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
state->dpmr_color_code = (int)state->dPMRVoiceFS2Frame.ColorCode[0];
|
|
||||||
|
|
||||||
|
//check other as well before assigning
|
||||||
|
if(state->dPMRVoiceFS2Frame.CalledIDOk) state->dpmr_color_code = (int)state->dPMRVoiceFS2Frame.ColorCode[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
//fprintf(stderr, " (CRC ERR) ");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display the source ID */
|
|
||||||
//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");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KRED);
|
fprintf (stderr, "%s", KRED);
|
||||||
fprintf(stderr, " (CRC ERR) \n");
|
fprintf(stderr, " Src=(CRC ERR) Channel Code =(CRC ERR)");
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* (NB_OF_DPMR_VOICE_FRAME_TO_DECODE == 2) */
|
if (state->dPMRVoiceFS2Frame.Version[0] == 3)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KRED);
|
||||||
|
fprintf (stderr, " Scrambler");
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
if (state->R != 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s", KYEL);
|
||||||
|
fprintf (stderr, " Key %05lld ", state->R );
|
||||||
|
fprintf (stderr, "%s", KNRM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Play only voice frames by first looking to see if there is a TCH voice in CommunicationMode,
|
//Play only voice frames by first looking to see if there is a TCH voice in CommunicationMode,
|
||||||
//then sending it to be processed by processMbeFrame, its much cleaner this way
|
|
||||||
short start = 0;
|
short start = 0;
|
||||||
short end = 4;
|
short end = 4;
|
||||||
|
|
||||||
|
//not really even sure why I made this loop
|
||||||
|
//I probably should actually read the manual again
|
||||||
for (short o = 0; o < 2; o++)
|
for (short o = 0; o < 2; o++)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//reset scrambler key seed on frame 0
|
||||||
|
if (state->dPMRVoiceFS2Frame.FrameNumbering[o] == 0) state->payload_miN = 0;
|
||||||
|
|
||||||
//depending on first or second TCH, set start and end variables appropriately
|
//depending on first or second TCH, set start and end variables appropriately
|
||||||
if (o == 1)
|
if (o == 1)
|
||||||
{
|
{
|
||||||
start = 4;
|
start = 4;
|
||||||
end = 8;
|
end = 8;
|
||||||
//add extra line break on second repitition only when dumping payload to console
|
|
||||||
if (opts->payload == 1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "\nCommunication Mode: %d\n", state->dPMRVoiceFS2Frame.CommunicationMode[o]);
|
|
||||||
//fprintf (stderr, "Encryption Mode: %d\n", state->dPMRVoiceFS2Frame.Version[o]);
|
//this is used so we can simply pass the voice here to the
|
||||||
//fprintf (stderr, "Superframe Number: %d", state->dPMRVoiceFS2Frame.FrameNumbering[o]); //should be 1-4, but may be same number on TCH 1 or TCH 2
|
//nxdn scrambler by telling mbe these are nxdn frames and to
|
||||||
|
//apply the same descramble method to them if necessary
|
||||||
|
int realsynctype = state->synctype;
|
||||||
|
|
||||||
|
// fprintf (stderr, "\nCommunication Mode: %d\n", state->dPMRVoiceFS2Frame.CommunicationMode[o]);
|
||||||
|
// fprintf (stderr, "Encryption Mode: %d\n", state->dPMRVoiceFS2Frame.Version[o]); //shows as 3 (manufacturer specific, 5.16) on the dPMR scrambler values received
|
||||||
|
// fprintf (stderr, "Superframe Number: %d", state->dPMRVoiceFS2Frame.FrameNumbering[o]);
|
||||||
|
|
||||||
if((state->dPMRVoiceFS2Frame.CommunicationMode[o] == 0) ||
|
if((state->dPMRVoiceFS2Frame.CommunicationMode[o] == 0) ||
|
||||||
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 1) ||
|
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 1) ||
|
||||||
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 5))
|
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 5))
|
||||||
{
|
{
|
||||||
|
|
||||||
//There are 4 AMBE voice samples per TCH
|
//check to see if we are using scrambler
|
||||||
|
if (state->dPMRVoiceFS2Frame.Version[o] == 3) //!= 0
|
||||||
|
{
|
||||||
|
state->synctype = 28; //fake it as nxdn
|
||||||
|
state->nxdn_cipher_type = 0x01; //turn on nxdn scrambler cipher
|
||||||
|
state->dmr_encL = 1; //flag on enc bit here so we can mute if no key provided
|
||||||
|
}
|
||||||
|
|
||||||
|
//flag back off if key is provided
|
||||||
|
if (state->R != 0) state->dmr_encL = 0;
|
||||||
|
|
||||||
|
//There are 4 AMBE voice frames per TCH
|
||||||
for(i = start; i < end; i++)
|
for(i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
processMbeFrame (opts, state, NULL, ambe_fr[i], NULL);
|
processMbeFrame (opts, state, NULL, ambe_fr[i], NULL);
|
||||||
} //End for(i = start; i < end); i++)
|
}
|
||||||
} //if comms and not encrypted
|
|
||||||
}//End for TCH for o loop
|
|
||||||
|
|
||||||
|
//set the correct sync type again and flag off the cipher
|
||||||
|
state->synctype = realsynctype;
|
||||||
|
state->nxdn_cipher_type = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
if (opts->errorbars == 1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//keep code below, could be handy cheat sheet for other info
|
//keep code below, could be handy cheat sheet for other info
|
||||||
#ifdef dPMR_PRINT_DEBUG_INFO
|
#ifdef dPMR_PRINT_DEBUG_INFO
|
||||||
|
|||||||
237
src/dsd_file.c
237
src/dsd_file.c
@@ -34,7 +34,7 @@ char * getTimeF(void) //get pretty hh:mm:ss timestamp
|
|||||||
}
|
}
|
||||||
|
|
||||||
char * getDateF(void) {
|
char * getDateF(void) {
|
||||||
char datename[120]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
|
char datename[80]; //32-bit needs this to be 80
|
||||||
char * curr2;
|
char * curr2;
|
||||||
struct tm * to;
|
struct tm * to;
|
||||||
time_t t;
|
time_t t;
|
||||||
@@ -45,8 +45,7 @@ char * getDateF(void) {
|
|||||||
return curr2;
|
return curr2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
|
||||||
saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
|
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
@@ -56,36 +55,22 @@ saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
|
|||||||
fputc (err, opts->mbe_out_f);
|
fputc (err, opts->mbe_out_f);
|
||||||
|
|
||||||
k = 0;
|
k = 0;
|
||||||
if (opts->payload == 1) //make opt variable later on to toggle this
|
|
||||||
{
|
|
||||||
//fprintf(stderr, "\n IMBE ");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 11; i++)
|
for (i = 0; i < 11; i++)
|
||||||
{
|
{
|
||||||
b = 0;
|
b = 0;
|
||||||
|
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
b = b << 1;
|
b = b << 1;
|
||||||
b = b + imbe_d[k];
|
b = b + imbe_d[k];
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
if (opts->payload == 1) //make opt variable later on to toggle this
|
fputc (b, opts->mbe_out_f);
|
||||||
{
|
}
|
||||||
//fprintf (stderr, "%02X", b);
|
|
||||||
}
|
|
||||||
fputc (b, opts->mbe_out_f);
|
|
||||||
}
|
|
||||||
if (opts->payload == 1)
|
|
||||||
{
|
|
||||||
//fprintf(stderr, " err = [%X] [%X] ", state->errs, state->errs2);
|
|
||||||
}
|
|
||||||
fflush (opts->mbe_out_f);
|
fflush (opts->mbe_out_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
||||||
saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
@@ -95,42 +80,49 @@ saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
|||||||
fputc (err, opts->mbe_out_f);
|
fputc (err, opts->mbe_out_f);
|
||||||
|
|
||||||
k = 0;
|
k = 0;
|
||||||
if (opts->payload == 1) //make opt variable later on to toggle this
|
for (i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "\n AMBE ");
|
b = 0;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
b = b << 1;
|
||||||
|
b = b + ambe_d[k];
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
fputc (b, opts->mbe_out_f);
|
||||||
}
|
}
|
||||||
//for (i = 0; i < 6; i++)
|
|
||||||
for (i = 0; i < 6; 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;
|
|
||||||
b = b + ambe_d[k];
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
if (opts->payload == 1 && i < 6) //make opt variable later on to toggle this
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "%02X", b);
|
|
||||||
}
|
|
||||||
if (opts->payload == 1 && i == 6) //7th octet should only contain 1 bit? value will be either 0x00 or 0x80?
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "%02X", b & 0x80); //7th octet should only contain 1 bit?
|
|
||||||
}
|
|
||||||
|
|
||||||
fputc (b, opts->mbe_out_f);
|
|
||||||
}
|
|
||||||
if (opts->payload == 1)
|
|
||||||
{
|
|
||||||
//fprintf(stderr, " err = [%X] [%X] ", state->errs, state->errs2);
|
|
||||||
}
|
|
||||||
b = ambe_d[48];
|
b = ambe_d[48];
|
||||||
fputc (b, opts->mbe_out_f);
|
fputc (b, opts->mbe_out_f);
|
||||||
fflush (opts->mbe_out_f);
|
fflush (opts->mbe_out_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void saveAmbe2450DataR (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
||||||
PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d) //for P25P1 and ProVoice
|
{
|
||||||
|
int i, j, k;
|
||||||
|
unsigned char b;
|
||||||
|
unsigned char err;
|
||||||
|
|
||||||
|
err = (unsigned char) state->errs2R;
|
||||||
|
fputc (err, opts->mbe_out_fR);
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
b = 0;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
b = b << 1;
|
||||||
|
b = b + ambe_d[k];
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
fputc (b, opts->mbe_out_fR);
|
||||||
|
}
|
||||||
|
b = ambe_d[48];
|
||||||
|
fputc (b, opts->mbe_out_fR);
|
||||||
|
fflush (opts->mbe_out_fR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d) //for P25P1 and ProVoice
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
@@ -165,8 +157,7 @@ PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d) //for P25P1 and
|
|||||||
//fprintf (stderr, "\n");
|
//fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
||||||
PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
@@ -333,14 +324,21 @@ openMbeInFile (dsd_opts * opts, dsd_state * state)
|
|||||||
cookie[2] = fgetc (opts->mbe_in_f);
|
cookie[2] = fgetc (opts->mbe_in_f);
|
||||||
cookie[3] = fgetc (opts->mbe_in_f);
|
cookie[3] = fgetc (opts->mbe_in_f);
|
||||||
cookie[4] = 0;
|
cookie[4] = 0;
|
||||||
|
//ambe+2
|
||||||
if (strstr (cookie, ".amb") != NULL)
|
if (strstr (cookie, ".amb") != NULL)
|
||||||
{
|
{
|
||||||
state->mbe_file_type = 1;
|
state->mbe_file_type = 1;
|
||||||
}
|
}
|
||||||
|
//p1 and pv
|
||||||
else if (strstr (cookie, ".imb") != NULL)
|
else if (strstr (cookie, ".imb") != NULL)
|
||||||
{
|
{
|
||||||
state->mbe_file_type = 0;
|
state->mbe_file_type = 0;
|
||||||
}
|
}
|
||||||
|
//d-star ambe
|
||||||
|
else if (strstr (cookie, ".dmb") != NULL)
|
||||||
|
{
|
||||||
|
state->mbe_file_type = 2;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state->mbe_file_type = -1;
|
state->mbe_file_type = -1;
|
||||||
@@ -349,7 +347,7 @@ openMbeInFile (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//much simpler version
|
//slot 1
|
||||||
void closeMbeOutFile (dsd_opts * opts, dsd_state * state)
|
void closeMbeOutFile (dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
if (opts->mbe_out == 1)
|
if (opts->mbe_out == 1)
|
||||||
@@ -360,48 +358,67 @@ void closeMbeOutFile (dsd_opts * opts, dsd_state * state)
|
|||||||
fclose (opts->mbe_out_f);
|
fclose (opts->mbe_out_f);
|
||||||
opts->mbe_out_f = NULL;
|
opts->mbe_out_f = NULL;
|
||||||
opts->mbe_out = 0;
|
opts->mbe_out = 0;
|
||||||
fprintf (stderr, "\nClosing MBE out file.");
|
fprintf (stderr, "\nClosing MBE out file 1.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
//slot 2
|
||||||
openMbeOutFile (dsd_opts * opts, dsd_state * state)
|
void closeMbeOutFileR (dsd_opts * opts, dsd_state * state)
|
||||||
|
{
|
||||||
|
if (opts->mbe_outR == 1)
|
||||||
|
{
|
||||||
|
if (opts->mbe_out_fR != NULL)
|
||||||
|
{
|
||||||
|
fflush (opts->mbe_out_fR);
|
||||||
|
fclose (opts->mbe_out_fR);
|
||||||
|
opts->mbe_out_fR = NULL;
|
||||||
|
opts->mbe_outR = 0;
|
||||||
|
fprintf (stderr, "\nClosing MBE out file 2.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void openMbeOutFile (dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
char ext[5];
|
char ext[5];
|
||||||
|
|
||||||
if ((state->synctype == 0) || (state->synctype == 1) || (state->synctype == 14) || (state->synctype == 15))
|
//phase 1 and provoice
|
||||||
{
|
if ( (state->synctype == 0) || (state->synctype == 1) || (state->synctype == 14) || (state->synctype == 15) )
|
||||||
sprintf (ext, ".imb");
|
{
|
||||||
}
|
sprintf (ext, ".imb");
|
||||||
else
|
}
|
||||||
{
|
//d-star
|
||||||
sprintf (ext, ".amb");
|
else if ( (state->synctype == 6) || (state->synctype == 7) || (state->synctype == 18) || (state->synctype == 19) )
|
||||||
}
|
{
|
||||||
|
sprintf (ext, ".dmb"); //new dstar file extension to make it read in and process properly
|
||||||
|
}
|
||||||
|
//dmr, nxdn, phase 2, x2-tdma
|
||||||
|
else sprintf (ext, ".amb");
|
||||||
|
|
||||||
// reset talkgroup id buffer
|
//reset talkgroup id buffer
|
||||||
for (i = 0; i < 12; i++)
|
for (i = 0; i < 12; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 25; j++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 25; j++)
|
state->tg[j][i] = 0;
|
||||||
{
|
|
||||||
state->tg[j][i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state->tgcount = 0;
|
state->tgcount = 0;
|
||||||
|
|
||||||
sprintf (opts->mbe_out_file, "%s %s%s", getDateF(), getTimeF(), ext);
|
sprintf (opts->mbe_out_file, "%s %s S1%s", getDateF(), getTimeF(), ext);
|
||||||
|
|
||||||
sprintf (opts->mbe_out_path, "%s%s", opts->mbe_out_dir, opts->mbe_out_file);
|
sprintf (opts->mbe_out_path, "%s%s", opts->mbe_out_dir, opts->mbe_out_file);
|
||||||
|
|
||||||
opts->mbe_out_f = fopen (opts->mbe_out_path, "w");
|
opts->mbe_out_f = fopen (opts->mbe_out_path, "w");
|
||||||
if (opts->mbe_out_f == NULL)
|
if (opts->mbe_out_f == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr,"Error, couldn't open %s\n", opts->mbe_out_path);
|
fprintf (stderr,"\nError, couldn't open %s for slot 1\n", opts->mbe_out_path);
|
||||||
}
|
}
|
||||||
else opts->mbe_out = 1;
|
else opts->mbe_out = 1;
|
||||||
|
|
||||||
@@ -411,8 +428,54 @@ openMbeOutFile (dsd_opts * opts, dsd_state * state)
|
|||||||
fflush (opts->mbe_out_f);
|
fflush (opts->mbe_out_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void openMbeOutFileR (dsd_opts * opts, dsd_state * state)
|
||||||
openWavOutFile (dsd_opts * opts, dsd_state * state)
|
{
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
char ext[5];
|
||||||
|
|
||||||
|
//phase 1 and provoice
|
||||||
|
if ( (state->synctype == 0) || (state->synctype == 1) || (state->synctype == 14) || (state->synctype == 15) )
|
||||||
|
{
|
||||||
|
sprintf (ext, ".imb");
|
||||||
|
}
|
||||||
|
//d-star
|
||||||
|
else if ( (state->synctype == 6) || (state->synctype == 7) || (state->synctype == 18) || (state->synctype == 19) )
|
||||||
|
{
|
||||||
|
sprintf (ext, ".dmb"); //new dstar file extension to make it read in and process properly
|
||||||
|
}
|
||||||
|
//dmr, nxdn, phase 2, x2-tdma
|
||||||
|
else sprintf (ext, ".amb");
|
||||||
|
|
||||||
|
//reset talkgroup id buffer
|
||||||
|
for (i = 0; i < 12; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 25; j++)
|
||||||
|
{
|
||||||
|
state->tg[j][i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->tgcount = 0;
|
||||||
|
|
||||||
|
sprintf (opts->mbe_out_fileR, "%s %s S2%s", getDateF(), getTimeF(), ext);
|
||||||
|
|
||||||
|
sprintf (opts->mbe_out_path, "%s%s", opts->mbe_out_dir, opts->mbe_out_fileR);
|
||||||
|
|
||||||
|
opts->mbe_out_fR = fopen (opts->mbe_out_path, "w");
|
||||||
|
if (opts->mbe_out_fR == NULL)
|
||||||
|
{
|
||||||
|
fprintf (stderr,"\nError, couldn't open %s for slot 2\n", opts->mbe_out_path);
|
||||||
|
}
|
||||||
|
else opts->mbe_outR = 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
fprintf (opts->mbe_out_fR, "%s", ext);
|
||||||
|
|
||||||
|
fflush (opts->mbe_out_fR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void openWavOutFile (dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
|
|
||||||
SF_INFO info;
|
SF_INFO info;
|
||||||
|
|||||||
451
src/dsd_frame.c
451
src/dsd_frame.c
@@ -87,8 +87,8 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
//NXDN FSW
|
//NXDN FSW
|
||||||
if ((state->synctype == 28) || (state->synctype == 29))
|
if ((state->synctype == 28) || (state->synctype == 29))
|
||||||
{
|
{
|
||||||
nxdn_frame (opts, state);
|
//MBEout restored, is not handled internally by nxdn_frame.c
|
||||||
//no MBEout...use symbol capture bin instead!
|
nxdn_frame (opts, state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((state->synctype == 6) || (state->synctype == 7))
|
else if ((state->synctype == 6) || (state->synctype == 7))
|
||||||
@@ -107,7 +107,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
state->nac = 0;
|
state->nac = 0;
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||||
{
|
{
|
||||||
openMbeOutFile (opts, state);
|
openMbeOutFile (opts, state); //dstar ambe files are read back incorrectly, need to change file extension to differentiate when doing a playback
|
||||||
}
|
}
|
||||||
sprintf (state->fsubtype, " VOICE ");
|
sprintf (state->fsubtype, " VOICE ");
|
||||||
processDSTAR (opts, state);
|
processDSTAR (opts, state);
|
||||||
@@ -128,9 +128,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
state->nac = 0;
|
state->nac = 0;
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||||
{
|
{
|
||||||
openMbeOutFile (opts, state);
|
openMbeOutFile (opts, state); //dstar ambe files are read back incorrectly, need to change file extension to differentiate when doing a playback
|
||||||
}
|
}
|
||||||
sprintf (state->fsubtype, " DATA ");
|
sprintf (state->fsubtype, " DATA ");
|
||||||
processDSTAR_HD (opts, state);
|
processDSTAR_HD (opts, state);
|
||||||
return;
|
return;
|
||||||
@@ -141,9 +141,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
//print manufacturer strings to branding, disabled 0x10 moto other systems can use that fid set
|
//print manufacturer strings to branding, disabled 0x10 moto other systems can use that fid set
|
||||||
//0x06 is trident, but when searching, apparently, they developed con+, but was bought by moto?
|
//0x06 is trident, but when searching, apparently, they developed con+, but was bought by moto?
|
||||||
if (state->dmr_mfid == 0x10) ; //sprintf (state->dmr_branding, "%s", "Motorola");
|
if (state->dmr_mfid == 0x10) ; //sprintf (state->dmr_branding, "%s", "Motorola");
|
||||||
else if (state->dmr_mfid == 0x68) sprintf (state->dmr_branding, "%s", "Hytera");
|
else if (state->dmr_mfid == 0x68) sprintf (state->dmr_branding, "%s", " Hytera");
|
||||||
else if (state->dmr_mfid == 0x58) sprintf (state->dmr_branding, "%s", "Tait");
|
else if (state->dmr_mfid == 0x58) sprintf (state->dmr_branding, "%s", " Tait");
|
||||||
|
|
||||||
//disabling these due to random data decodes setting an odd mfid, could be legit, but only for that one packet?
|
//disabling these due to random data decodes setting an odd mfid, could be legit, but only for that one packet?
|
||||||
//or, its just a decode error somewhere
|
//or, its just a decode error somewhere
|
||||||
@@ -164,70 +164,58 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
//disable so radio id doesn't blink in and out during ncurses and aggressive_framesync
|
//disable so radio id doesn't blink in and out during ncurses and aggressive_framesync
|
||||||
state->nac = 0;
|
state->nac = 0;
|
||||||
//state->lastsrc = 0;
|
|
||||||
//state->lasttg = 0;
|
|
||||||
//state->lastsrcR = 0;
|
|
||||||
//state->lasttgR = 0;
|
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
|
{
|
||||||
|
if (opts->verbose > 0)
|
||||||
{
|
{
|
||||||
if (opts->verbose > 0)
|
level = (int) state->max / 164;
|
||||||
{
|
//fprintf (stderr,"inlvl: %2i%% ", level);
|
||||||
level = (int) state->max / 164;
|
|
||||||
//fprintf (stderr,"inlvl: %2i%% ", level);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( (state->synctype == 11) || (state->synctype == 12) || (state->synctype == 32) ) //DMR Voice Modes
|
if ( (state->synctype == 11) || (state->synctype == 12) || (state->synctype == 32) ) //DMR Voice Modes
|
||||||
|
{
|
||||||
|
|
||||||
|
sprintf (state->fsubtype, " VOICE ");
|
||||||
|
if (opts->dmr_stereo == 0 && state->synctype < 32) // -T option for DMR (TDMA) stereo
|
||||||
{
|
{
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL) && opts->dmr_stereo == 0)
|
sprintf (state->slot1light, " slot1 ");
|
||||||
{
|
sprintf (state->slot2light, " slot2 ");
|
||||||
openMbeOutFile (opts, state);
|
//we can safely open MBE on any MS or mono handling
|
||||||
}
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
sprintf (state->fsubtype, " VOICE ");
|
dmrMSBootstrap (opts, state);
|
||||||
if (opts->dmr_stereo == 0 && state->synctype < 32) // -T option for DMR (TDMA) stereo
|
|
||||||
{
|
|
||||||
sprintf (state->slot1light, " slot1 ");
|
|
||||||
sprintf (state->slot2light, " slot2 ");
|
|
||||||
dmrMSBootstrap (opts, state);
|
|
||||||
}
|
|
||||||
if (opts->dmr_mono == 1 && state->synctype == 32)
|
|
||||||
{
|
|
||||||
// fprintf (stderr, "%s", KRED);
|
|
||||||
// fprintf (stderr, "Please use XDMA or DMR Stereo to decode MS/Simplex \n");
|
|
||||||
// fprintf (stderr, "%s", KNRM);
|
|
||||||
dmrMSBootstrap (opts, state);
|
|
||||||
}
|
|
||||||
if (opts->dmr_stereo == 1) //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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (opts->dmr_mono == 1 && state->synctype == 32)
|
||||||
|
{
|
||||||
|
//we can safely open MBE on any MS or mono handling
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
|
dmrMSBootstrap (opts, state);
|
||||||
|
}
|
||||||
|
if (opts->dmr_stereo == 1) //opts->dmr_stereo == 1
|
||||||
|
{
|
||||||
|
state->dmr_stereo = 1; //set the state to 1 when handling pure voice frames
|
||||||
|
if (state->synctype > 31 )
|
||||||
|
{
|
||||||
|
//we can safely open MBE on any MS or mono handling
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
|
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
|
else if ( (state->synctype == 33) || (state->synctype == 34) ) //MS Data and RC data
|
||||||
{
|
{
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
dmrMSData (opts, state);
|
dmrMSData (opts, state);
|
||||||
// if (opts->dmr_stereo == 0)
|
|
||||||
// {
|
|
||||||
// closeMbeOutFile (opts, state);
|
|
||||||
// state->err_str[0] = 0;
|
|
||||||
// fprintf (stderr, "%s", KRED);
|
|
||||||
// fprintf (stderr, "Please use XDMA or DMR Stereo to decode MS/Simplex \n");
|
|
||||||
// fprintf (stderr, "%s", KNRM);
|
|
||||||
// }
|
|
||||||
// if (opts->dmr_stereo == 1)
|
|
||||||
// {
|
|
||||||
// dmrMSData (opts, state);
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (opts->dmr_stereo == 0)
|
if (opts->dmr_stereo == 0)
|
||||||
{
|
{
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
state->err_str[0] = 0;
|
state->err_str[0] = 0;
|
||||||
sprintf (state->slot1light, " slot1 ");
|
sprintf (state->slot1light, " slot1 ");
|
||||||
sprintf (state->slot2light, " slot2 ");
|
sprintf (state->slot2light, " slot2 ");
|
||||||
@@ -237,6 +225,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
//switch dmr_stereo to 0 when handling BS data frame syncs with processDMRdata
|
//switch dmr_stereo to 0 when handling BS data frame syncs with processDMRdata
|
||||||
if (opts->dmr_stereo == 1)
|
if (opts->dmr_stereo == 1)
|
||||||
{
|
{
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
state->dmr_stereo = 0; //set the state to zero for handling pure data frames
|
state->dmr_stereo = 0; //set the state to zero for handling pure data frames
|
||||||
sprintf (state->slot1light, " slot1 ");
|
sprintf (state->slot1light, " slot1 ");
|
||||||
sprintf (state->slot2light, " slot2 ");
|
sprintf (state->slot2light, " slot2 ");
|
||||||
@@ -246,7 +237,8 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((state->synctype >= 2) && (state->synctype <= 5))
|
//X2-TDMA
|
||||||
|
else if ((state->synctype >= 2) && (state->synctype <= 5))
|
||||||
{
|
{
|
||||||
state->nac = 0;
|
state->nac = 0;
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
@@ -256,15 +248,15 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
if ((state->synctype == 3) || (state->synctype == 4))
|
if ((state->synctype == 3) || (state->synctype == 4))
|
||||||
{
|
{
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||||
{
|
{
|
||||||
openMbeOutFile (opts, state);
|
openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
sprintf (state->fsubtype, " VOICE ");
|
sprintf (state->fsubtype, " VOICE ");
|
||||||
processX2TDMAvoice (opts, state);
|
processX2TDMAvoice (opts, state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
state->err_str[0] = 0;
|
state->err_str[0] = 0;
|
||||||
processX2TDMAdata (opts, state);
|
processX2TDMAdata (opts, state);
|
||||||
}
|
}
|
||||||
@@ -272,21 +264,18 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
else if ((state->synctype == 14) || (state->synctype == 15))
|
else if ((state->synctype == 14) || (state->synctype == 15))
|
||||||
{
|
{
|
||||||
//state->nac = 0;
|
|
||||||
//state->lastsrc = 0;
|
|
||||||
//state->lasttg = 0;
|
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
|
{
|
||||||
|
if (opts->verbose > 0)
|
||||||
{
|
{
|
||||||
if (opts->verbose > 0)
|
level = (int) state->max / 164;
|
||||||
{
|
//fprintf (stderr,"inlvl: %2i%% ", level);
|
||||||
level = (int) state->max / 164;
|
|
||||||
//fprintf (stderr,"inlvl: %2i%% ", level);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||||
{
|
{
|
||||||
openMbeOutFile (opts, state);
|
openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
sprintf (state->fsubtype, " VOICE ");
|
sprintf (state->fsubtype, " VOICE ");
|
||||||
processProVoice (opts, state);
|
processProVoice (opts, state);
|
||||||
return;
|
return;
|
||||||
@@ -294,6 +283,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
//edacs
|
//edacs
|
||||||
else if ((state->synctype == 37) || (state->synctype == 38))
|
else if ((state->synctype == 37) || (state->synctype == 38))
|
||||||
{
|
{
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
edacs (opts, state);
|
edacs (opts, state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -313,13 +303,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
//P25 P2
|
//P25 P2
|
||||||
else if ((state->synctype == 35) || (state->synctype == 36))
|
else if ((state->synctype == 35) || (state->synctype == 36))
|
||||||
{
|
{
|
||||||
//Do stuff
|
//relocate MBEout to inside frame handling
|
||||||
//fprintf(stderr, "YSF Sync! \n");
|
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
|
||||||
{
|
|
||||||
//openMbeOutFile (opts, state);
|
|
||||||
}
|
|
||||||
//sprintf(state->fsubtype, " VOICE ");
|
|
||||||
processP2(opts, state);
|
processP2(opts, state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -328,6 +312,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
/* dPMR Frame Sync 1 */
|
/* dPMR Frame Sync 1 */
|
||||||
fprintf(stderr, "dPMR Frame Sync 1 ");
|
fprintf(stderr, "dPMR Frame Sync 1 ");
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
else if ((state->synctype == 21) || (state->synctype == 25))
|
else if ((state->synctype == 21) || (state->synctype == 25))
|
||||||
{
|
{
|
||||||
@@ -346,12 +331,12 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
state->nac = 0;
|
state->nac = 0;
|
||||||
|
|
||||||
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
|
||||||
{
|
{
|
||||||
openMbeOutFile (opts, state);
|
openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
sprintf(state->fsubtype, " VOICE ");
|
sprintf(state->fsubtype, " VOICE ");
|
||||||
processdPMRvoice (opts, state);
|
processdPMRvoice (opts, state);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -360,11 +345,13 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
/* dPMR Frame Sync 3 */
|
/* dPMR Frame Sync 3 */
|
||||||
fprintf(stderr, "dPMR Frame Sync 3 ");
|
fprintf(stderr, "dPMR Frame Sync 3 ");
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
else if ((state->synctype == 23) || (state->synctype == 27))
|
else if ((state->synctype == 23) || (state->synctype == 27))
|
||||||
{
|
{
|
||||||
/* dPMR Frame Sync 4 */
|
/* dPMR Frame Sync 4 */
|
||||||
fprintf(stderr, "dPMR Frame Sync 4 ");
|
fprintf(stderr, "dPMR Frame Sync 4 ");
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
//dPMR
|
//dPMR
|
||||||
else //P25
|
else //P25
|
||||||
@@ -463,15 +450,15 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
// Header Data Unit
|
// Header Data Unit
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," HDU\n");
|
fprintf (stderr," HDU\n");
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
{
|
{
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
openMbeOutFile (opts, state);
|
if (opts->mbe_out_f == NULL) openMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
||||||
state->lastp25type = 2;
|
state->lastp25type = 2;
|
||||||
state->dmrburstL = 25;
|
state->dmrburstL = 25;
|
||||||
@@ -483,17 +470,17 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
// Logical Link Data Unit 1
|
// Logical Link Data Unit 1
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," LDU1 ");
|
fprintf (stderr," LDU1 ");
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
|
{
|
||||||
|
if (opts->mbe_out_f == NULL)
|
||||||
{
|
{
|
||||||
if (opts->mbe_out_f == NULL)
|
openMbeOutFile (opts, state);
|
||||||
{
|
|
||||||
openMbeOutFile (opts, state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
state->lastp25type = 1;
|
state->lastp25type = 1;
|
||||||
state->dmrburstL = 26;
|
state->dmrburstL = 26;
|
||||||
state->currentslot = 0;
|
state->currentslot = 0;
|
||||||
@@ -514,27 +501,27 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
if (state->lastp25type != 1)
|
if (state->lastp25type != 1)
|
||||||
{
|
{
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr,"\n Ignoring LDU2 not preceeded by LDU1\n");
|
fprintf (stderr,"\n Ignoring LDU2 not preceeded by LDU1\n");
|
||||||
}
|
}
|
||||||
state->lastp25type = 0;
|
state->lastp25type = 0;
|
||||||
sprintf (state->fsubtype, " ");
|
sprintf (state->fsubtype, " ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," LDU2 ");
|
fprintf (stderr," LDU2 ");
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
|
{
|
||||||
|
if (opts->mbe_out_f == NULL)
|
||||||
{
|
{
|
||||||
if (opts->mbe_out_f == NULL)
|
openMbeOutFile (opts, state);
|
||||||
{
|
|
||||||
openMbeOutFile (opts, state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
state->lastp25type = 2;
|
state->lastp25type = 2;
|
||||||
sprintf (state->fsubtype, " LDU2 ");
|
sprintf (state->fsubtype, " LDU2 ");
|
||||||
state->numtdulc = 0;
|
state->numtdulc = 0;
|
||||||
@@ -546,14 +533,14 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
// Terminator with subsequent Link Control
|
// Terminator with subsequent Link Control
|
||||||
state->dmrburstL = 28;
|
state->dmrburstL = 28;
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," TDULC\n");
|
fprintf (stderr," TDULC\n");
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
{
|
{
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
||||||
state->lasttg = 0;
|
state->lasttg = 0;
|
||||||
state->lastsrc = 0;
|
state->lastsrc = 0;
|
||||||
@@ -562,9 +549,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
sprintf (state->fsubtype, " TDULC ");
|
sprintf (state->fsubtype, " TDULC ");
|
||||||
state->numtdulc++;
|
state->numtdulc++;
|
||||||
if ((opts->resume > 0) && (state->numtdulc > opts->resume))
|
if ((opts->resume > 0) && (state->numtdulc > opts->resume))
|
||||||
{
|
{
|
||||||
resumeScan (opts, state);
|
resumeScan (opts, state);
|
||||||
}
|
}
|
||||||
processTDULC (opts, state);
|
processTDULC (opts, state);
|
||||||
state->err_str[0] = 0;
|
state->err_str[0] = 0;
|
||||||
}
|
}
|
||||||
@@ -573,14 +560,14 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
// Terminator without subsequent Link Control
|
// Terminator without subsequent Link Control
|
||||||
state->dmrburstL = 28;
|
state->dmrburstL = 28;
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," TDU\n");
|
fprintf (stderr," TDU\n");
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
{
|
{
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
}
|
||||||
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
||||||
state->lasttg = 0;
|
state->lasttg = 0;
|
||||||
state->lastsrc = 0;
|
state->lastsrc = 0;
|
||||||
@@ -594,120 +581,126 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
state->dmrburstL = 29;
|
state->dmrburstL = 29;
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," TSBK");
|
fprintf (stderr," TSBK");
|
||||||
}
|
}
|
||||||
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
|
{
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
}
|
||||||
if (opts->resume > 0)
|
if (opts->resume > 0)
|
||||||
{
|
{
|
||||||
resumeScan (opts, state);
|
resumeScan (opts, state);
|
||||||
}
|
}
|
||||||
state->lasttg = 0;
|
state->lasttg = 0;
|
||||||
state->lastsrc = 0;
|
state->lastsrc = 0;
|
||||||
state->lastp25type = 3;
|
state->lastp25type = 3;
|
||||||
sprintf (state->fsubtype, " TSBK ");
|
sprintf (state->fsubtype, " TSBK ");
|
||||||
|
|
||||||
// Now processing NID
|
|
||||||
processTSBK(opts, state);
|
processTSBK(opts, state);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (strcmp (duid, "30") == 0)
|
else if (strcmp (duid, "30") == 0)
|
||||||
{
|
{
|
||||||
if (opts->errorbars == 1)
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
printFrameInfo (opts, state);
|
printFrameInfo (opts, state);
|
||||||
fprintf (stderr," PDU\n");
|
fprintf (stderr," PDU\n"); //multi block/packet PDU
|
||||||
}
|
}
|
||||||
if (opts->resume > 0)
|
|
||||||
{
|
|
||||||
resumeScan (opts, state);
|
|
||||||
}
|
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
if (opts->mbe_out_dir[0] != 0)
|
||||||
{
|
{
|
||||||
if (opts->mbe_out_f == NULL)
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
{
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
openMbeOutFile (opts, state);
|
}
|
||||||
}
|
if (opts->resume > 0)
|
||||||
}
|
{
|
||||||
|
resumeScan (opts, state);
|
||||||
|
}
|
||||||
state->lastp25type = 4;
|
state->lastp25type = 4;
|
||||||
sprintf (state->fsubtype, " PDU ");
|
sprintf (state->fsubtype, " PDU ");
|
||||||
}
|
}
|
||||||
// try to guess based on previous frame if unknown type
|
|
||||||
else if (state->lastp25type == 1)
|
|
||||||
{
|
|
||||||
if (opts->errorbars == 1)
|
|
||||||
{
|
|
||||||
printFrameInfo (opts, state);
|
|
||||||
fprintf (stderr,"(LDU2) ");
|
|
||||||
}
|
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
|
||||||
{
|
|
||||||
if (opts->mbe_out_f == NULL)
|
|
||||||
{
|
|
||||||
openMbeOutFile (opts, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//state->lastp25type = 0;
|
|
||||||
// Guess that the state is LDU2
|
|
||||||
state->lastp25type = 2;
|
|
||||||
sprintf (state->fsubtype, "(LDU2) ");
|
|
||||||
state->numtdulc = 0;
|
|
||||||
processLDU2 (opts, state);
|
|
||||||
}
|
|
||||||
else if (state->lastp25type == 2)
|
|
||||||
{
|
|
||||||
if (opts->errorbars == 1)
|
|
||||||
{
|
|
||||||
printFrameInfo (opts, state);
|
|
||||||
fprintf (stderr,"(LDU1) ");
|
|
||||||
}
|
|
||||||
if (opts->mbe_out_dir[0] != 0)
|
|
||||||
{
|
|
||||||
if (opts->mbe_out_f == NULL)
|
|
||||||
{
|
|
||||||
openMbeOutFile (opts, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//state->lastp25type = 0;
|
|
||||||
// Guess that the state is LDU1
|
|
||||||
state->lastp25type = 1;
|
|
||||||
sprintf (state->fsubtype, "(LDU1) ");
|
|
||||||
state->numtdulc = 0;
|
|
||||||
processLDU1 (opts, state);
|
|
||||||
}
|
|
||||||
else if (state->lastp25type == 3)
|
|
||||||
{
|
|
||||||
if (opts->errorbars == 1)
|
|
||||||
{
|
|
||||||
printFrameInfo (opts, state);
|
|
||||||
fprintf (stderr," (TSBK)\n");
|
|
||||||
}
|
|
||||||
//state->lastp25type = 0;
|
|
||||||
// Guess that the state is TSBK
|
|
||||||
state->lastp25type = 3;
|
|
||||||
sprintf (state->fsubtype, "(TSBK) ");
|
|
||||||
|
|
||||||
// Now processing NID
|
// try to guess based on previous frame if unknown type
|
||||||
skipDibit (opts, state, 328-25);
|
// disabling the guessing game on P1
|
||||||
}
|
|
||||||
else if (state->lastp25type == 4)
|
// else if (state->lastp25type == 1)
|
||||||
{
|
// {
|
||||||
if (opts->errorbars == 1)
|
// if (opts->errorbars == 1)
|
||||||
{
|
// {
|
||||||
printFrameInfo (opts, state);
|
// printFrameInfo (opts, state);
|
||||||
fprintf (stderr," (PDU)\n");
|
// fprintf (stderr,"(LDU2) ");
|
||||||
}
|
// }
|
||||||
state->lastp25type = 0;
|
// // if (opts->mbe_out_dir[0] != 0)
|
||||||
}
|
// // {
|
||||||
|
// // if (opts->mbe_out_f == NULL)
|
||||||
|
// // {
|
||||||
|
// // openMbeOutFile (opts, state);
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// //state->lastp25type = 0;
|
||||||
|
// // Guess that the state is LDU2
|
||||||
|
// state->lastp25type = 2;
|
||||||
|
// sprintf (state->fsubtype, "(LDU2) ");
|
||||||
|
// state->numtdulc = 0;
|
||||||
|
// processLDU2 (opts, state);
|
||||||
|
// }
|
||||||
|
// else if (state->lastp25type == 2)
|
||||||
|
// {
|
||||||
|
// if (opts->errorbars == 1)
|
||||||
|
// {
|
||||||
|
// printFrameInfo (opts, state);
|
||||||
|
// fprintf (stderr,"(LDU1) ");
|
||||||
|
// }
|
||||||
|
// if (opts->mbe_out_dir[0] != 0)
|
||||||
|
// {
|
||||||
|
// if (opts->mbe_out_f == NULL)
|
||||||
|
// {
|
||||||
|
// openMbeOutFile (opts, state);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //state->lastp25type = 0;
|
||||||
|
// // Guess that the state is LDU1
|
||||||
|
// state->lastp25type = 1;
|
||||||
|
// sprintf (state->fsubtype, "(LDU1) ");
|
||||||
|
// state->numtdulc = 0;
|
||||||
|
// processLDU1 (opts, state);
|
||||||
|
// }
|
||||||
|
// else if (state->lastp25type == 3)
|
||||||
|
// {
|
||||||
|
// if (opts->errorbars == 1)
|
||||||
|
// {
|
||||||
|
// printFrameInfo (opts, state);
|
||||||
|
// fprintf (stderr," (TSBK)\n");
|
||||||
|
// }
|
||||||
|
// //state->lastp25type = 0;
|
||||||
|
// // Guess that the state is TSBK
|
||||||
|
// state->lastp25type = 3;
|
||||||
|
// sprintf (state->fsubtype, "(TSBK) ");
|
||||||
|
|
||||||
|
// // Now processing NID
|
||||||
|
// skipDibit (opts, state, 328-25);
|
||||||
|
// }
|
||||||
|
// else if (state->lastp25type == 4)
|
||||||
|
// {
|
||||||
|
// if (opts->errorbars == 1)
|
||||||
|
// {
|
||||||
|
// printFrameInfo (opts, state);
|
||||||
|
// fprintf (stderr," (PDU)\n");
|
||||||
|
// }
|
||||||
|
// state->lastp25type = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
state->lastp25type = 0;
|
||||||
|
sprintf (state->fsubtype, " ");
|
||||||
|
if (opts->errorbars == 1)
|
||||||
{
|
{
|
||||||
state->lastp25type = 0;
|
printFrameInfo (opts, state);
|
||||||
sprintf (state->fsubtype, " ");
|
fprintf (stderr," duid:%s *Unknown DUID*\n", duid); //prints on dPMR frame 3
|
||||||
if (opts->errorbars == 1)
|
// fprintf (stderr, "\n"); //prints on dPMR frame 3
|
||||||
{
|
|
||||||
printFrameInfo (opts, state);
|
|
||||||
fprintf (stderr," duid:%s *Unknown DUID*\n", duid); //prints on dPMR frame 3
|
|
||||||
// fprintf (stderr, "\n"); //prints on dPMR frame 3
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,3 +145,48 @@ int csvChanImport(dsd_opts * opts, dsd_state * state) //channel map import
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support for NXDN
|
||||||
|
{
|
||||||
|
char filename[1024] = "filename.csv";
|
||||||
|
sprintf (filename, "%s", opts->key_in_file);
|
||||||
|
|
||||||
|
char buffer[BSIZE];
|
||||||
|
FILE * fp;
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
printf("Unable to open file '%s'\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int row_count = 0;
|
||||||
|
int field_count = 0;
|
||||||
|
unsigned long long int keynumber;
|
||||||
|
|
||||||
|
while (fgets(buffer, BSIZE, fp)) {
|
||||||
|
field_count = 0;
|
||||||
|
row_count++;
|
||||||
|
if (row_count == 1)
|
||||||
|
continue; //don't want labels
|
||||||
|
char * field = strtok(buffer, ","); //seperate by comma
|
||||||
|
while (field) {
|
||||||
|
|
||||||
|
if (field_count == 0)
|
||||||
|
{
|
||||||
|
sscanf (field, "%lld", &keynumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field_count == 1)
|
||||||
|
{
|
||||||
|
sscanf (field, "%lld", &state->rkey_array[keynumber]);
|
||||||
|
}
|
||||||
|
|
||||||
|
field = strtok(NULL, ",");
|
||||||
|
field_count++;
|
||||||
|
}
|
||||||
|
fprintf (stderr, "Key [%03lld] [%05lld]", keynumber, state->rkey_array[keynumber]);
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
156
src/dsd_main.c
156
src/dsd_main.c
@@ -52,7 +52,7 @@ char * FM_banner[9] = {
|
|||||||
" ██║ ██║ ╚═══██╗██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
|
" ██║ ██║ ╚═══██╗██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
|
||||||
" ██████╔╝██████╔╝██████╔╝ ██║ ██║ ╚═╝ ██║███████╗",
|
" ██████╔╝██████╔╝██████╔╝ ██║ ██║ ╚═╝ ██║███████╗",
|
||||||
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝",
|
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝",
|
||||||
" Lite Edition v2.0.0-6-gc44e039 Windows 32-bit RC1 "
|
" 'Lite' Edition v2.0.0-28-ga02f992 Windows 32-bit RC3 "
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -69,6 +69,7 @@ comp (const void *a, const void *b)
|
|||||||
//struct for checking existence of directory to write to
|
//struct for checking existence of directory to write to
|
||||||
struct stat st = {0};
|
struct stat st = {0};
|
||||||
char wav_file_directory[1024] = {0};
|
char wav_file_directory[1024] = {0};
|
||||||
|
char dsp_filename[1024] = {0};
|
||||||
unsigned long long int p2vars = 0;
|
unsigned long long int p2vars = 0;
|
||||||
|
|
||||||
char * pEnd; //bugfix
|
char * pEnd; //bugfix
|
||||||
@@ -135,10 +136,11 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
|||||||
state->dmr_payload_p = state->dibit_buf + 200;
|
state->dmr_payload_p = state->dibit_buf + 200;
|
||||||
memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
|
memset (state->dmr_payload_buf, 0, sizeof (int) * 200);
|
||||||
//dmr buffer end
|
//dmr buffer end
|
||||||
if (opts->mbe_out_f != NULL)
|
|
||||||
{
|
//close MBE out files
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
state->jitter = -1;
|
state->jitter = -1;
|
||||||
state->lastsynctype = -1;
|
state->lastsynctype = -1;
|
||||||
state->carrier = 0;
|
state->carrier = 0;
|
||||||
@@ -301,6 +303,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
//initialize unified dmr pdu 'superframe'
|
//initialize unified dmr pdu 'superframe'
|
||||||
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
|
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
|
||||||
|
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
|
||||||
|
|
||||||
//init confirmed data individual block crc as invalid
|
//init confirmed data individual block crc as invalid
|
||||||
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
||||||
@@ -319,8 +322,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
|||||||
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
|
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
|
||||||
|
|
||||||
//REMUS! multi-purpose call_string
|
//REMUS! multi-purpose call_string
|
||||||
sprintf (state->call_string[0], "%s", " "); //20 spaces
|
sprintf (state->call_string[0], "%s", " "); //21 spaces
|
||||||
sprintf (state->call_string[1], "%s", " "); //20 spaces
|
sprintf (state->call_string[1], "%s", " "); //21 spaces
|
||||||
|
|
||||||
if (time(NULL) - state->last_cc_sync_time > 30) //thirty seconds of no carrier
|
if (time(NULL) - state->last_cc_sync_time > 30) //thirty seconds of no carrier
|
||||||
{
|
{
|
||||||
@@ -334,6 +337,17 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
|||||||
opts->p25_is_tuned = 0;
|
opts->p25_is_tuned = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts->dPMR_next_part_of_superframe = 0;
|
||||||
|
|
||||||
|
state->dPMRVoiceFS2Frame.CalledIDOk = 0;
|
||||||
|
state->dPMRVoiceFS2Frame.CallingIDOk = 0;
|
||||||
|
memset(state->dPMRVoiceFS2Frame.CalledID, 0, 8);
|
||||||
|
memset(state->dPMRVoiceFS2Frame.CallingID, 0, 8);
|
||||||
|
memset(state->dPMRVoiceFS2Frame.Version, 0, 8);
|
||||||
|
|
||||||
|
sprintf (state->dpmr_caller_id, "%s", " ");
|
||||||
|
sprintf (state->dpmr_target_id, "%s", " ");
|
||||||
|
|
||||||
} //nocarrier
|
} //nocarrier
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -364,8 +378,10 @@ initOpts (dsd_opts * opts)
|
|||||||
opts->playoffsetR = 0;
|
opts->playoffsetR = 0;
|
||||||
opts->mbe_out_dir[0] = 0;
|
opts->mbe_out_dir[0] = 0;
|
||||||
opts->mbe_out_file[0] = 0;
|
opts->mbe_out_file[0] = 0;
|
||||||
|
opts->mbe_out_fileR[0] = 0; //second slot on a TDMA system
|
||||||
opts->mbe_out_path[0] = 0;
|
opts->mbe_out_path[0] = 0;
|
||||||
opts->mbe_out_f = NULL;
|
opts->mbe_out_f = NULL;
|
||||||
|
opts->mbe_out_fR = NULL; //second slot on a TDMA system
|
||||||
opts->audio_gain = 0; //0
|
opts->audio_gain = 0; //0
|
||||||
opts->audio_gainR = 0; //0
|
opts->audio_gainR = 0; //0
|
||||||
opts->audio_out = 1;
|
opts->audio_out = 1;
|
||||||
@@ -378,11 +394,13 @@ initOpts (dsd_opts * opts)
|
|||||||
opts->group_in_file[0] = 0;
|
opts->group_in_file[0] = 0;
|
||||||
opts->lcn_in_file[0] = 0;
|
opts->lcn_in_file[0] = 0;
|
||||||
opts->chan_in_file[0] = 0;
|
opts->chan_in_file[0] = 0;
|
||||||
|
opts->key_in_file[0] = 0;
|
||||||
//end import filenames
|
//end import filenames
|
||||||
opts->szNumbers[0] = 0;
|
opts->szNumbers[0] = 0;
|
||||||
opts->symbol_out_f = NULL;
|
opts->symbol_out_f = NULL;
|
||||||
opts->symbol_out = 0;
|
opts->symbol_out = 0;
|
||||||
opts->mbe_out = 0;
|
opts->mbe_out = 0;
|
||||||
|
opts->mbe_outR = 0; //second slot on a TDMA system
|
||||||
opts->wav_out_f = NULL;
|
opts->wav_out_f = NULL;
|
||||||
opts->wav_out_fR = NULL;
|
opts->wav_out_fR = NULL;
|
||||||
opts->wav_out_raw = NULL;
|
opts->wav_out_raw = NULL;
|
||||||
@@ -504,12 +522,18 @@ initOpts (dsd_opts * opts)
|
|||||||
//Trunking - Tune Data Calls
|
//Trunking - Tune Data Calls
|
||||||
opts->trunk_tune_data_calls = 0; //disabled by default
|
opts->trunk_tune_data_calls = 0; //disabled by default
|
||||||
|
|
||||||
|
opts->dPMR_next_part_of_superframe = 0;
|
||||||
|
|
||||||
//OSS audio - Slot Preference
|
//OSS audio - Slot Preference
|
||||||
//slot preference is used during OSS audio playback to
|
//slot preference is used during OSS audio playback to
|
||||||
//prefer one tdma voice slot over another when both are playing back
|
//prefer one tdma voice slot over another when both are playing back
|
||||||
//this is a fix to cygwin stuttering when both slots have voice
|
//this is a fix to cygwin stuttering when both slots have voice
|
||||||
opts->slot_preference = 0; //default prefer slot 1 -- state->currentslot = 0;
|
opts->slot_preference = 0; //default prefer slot 1 -- state->currentslot = 0;
|
||||||
|
|
||||||
|
//dsp structured file
|
||||||
|
opts->dsp_out_file[0] = 0;
|
||||||
|
opts->use_dsp_output = 0;
|
||||||
|
|
||||||
} //initopts
|
} //initopts
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -649,8 +673,6 @@ initState (dsd_state * state)
|
|||||||
state->payload_miN = 0;
|
state->payload_miN = 0;
|
||||||
|
|
||||||
state->dpmr_color_code = -1;
|
state->dpmr_color_code = -1;
|
||||||
state->dpmr_caller_id = 0;
|
|
||||||
state->dpmr_target_id = 0;
|
|
||||||
|
|
||||||
state->payload_mi = 0;
|
state->payload_mi = 0;
|
||||||
state->payload_miR = 0;
|
state->payload_miR = 0;
|
||||||
@@ -683,10 +705,12 @@ initState (dsd_state * state)
|
|||||||
state->dmr_stereo = 0; //1, or 0?
|
state->dmr_stereo = 0; //1, or 0?
|
||||||
state->dmrburstL = 17; //initialize at higher value than possible
|
state->dmrburstL = 17; //initialize at higher value than possible
|
||||||
state->dmrburstR = 17; //17 in char array is set for ERR
|
state->dmrburstR = 17; //17 in char array is set for ERR
|
||||||
state->dmr_so = 0;
|
state->dmr_so = 0;
|
||||||
state->dmr_soR = 0;
|
state->dmr_soR = 0;
|
||||||
state->dmr_fid = 0;
|
state->dmr_fid = 0;
|
||||||
state->dmr_fidR = 0;
|
state->dmr_fidR = 0;
|
||||||
|
state->dmr_flco = 0;
|
||||||
|
state->dmr_flcoR = 0;
|
||||||
state->dmr_ms_mode = 0;
|
state->dmr_ms_mode = 0;
|
||||||
|
|
||||||
state->HYTL = 0;
|
state->HYTL = 0;
|
||||||
@@ -730,6 +754,8 @@ initState (dsd_state * state)
|
|||||||
state->p2_wacn = 0;
|
state->p2_wacn = 0;
|
||||||
state->p2_sysid = 0;
|
state->p2_sysid = 0;
|
||||||
state->p2_cc = 0;
|
state->p2_cc = 0;
|
||||||
|
state->p2_siteid = 0;
|
||||||
|
state->p2_rfssid = 0;
|
||||||
state->p2_hardset = 0;
|
state->p2_hardset = 0;
|
||||||
state->p2_is_lcch = 0;
|
state->p2_is_lcch = 0;
|
||||||
state->p25_cc_is_tdma = 2; //init on 2, TSBK NET_STS will set 0, TDMA NET_STS will set 1. //used to determine if we need to change symbol rate when cc hunting
|
state->p25_cc_is_tdma = 2; //init on 2, TSBK NET_STS will set 0, TDMA NET_STS will set 1. //used to determine if we need to change symbol rate when cc hunting
|
||||||
@@ -779,9 +805,6 @@ initState (dsd_state * state)
|
|||||||
//dmr trunking/ncurses stuff
|
//dmr trunking/ncurses stuff
|
||||||
state->dmr_rest_channel = -1; //init on -1
|
state->dmr_rest_channel = -1; //init on -1
|
||||||
state->dmr_mfid = -1; //
|
state->dmr_mfid = -1; //
|
||||||
state->dmr_tuned_lcn = -1; //logical slot, lcn * ts?
|
|
||||||
state->dmr_vc_lcn = -1; //
|
|
||||||
state->dmr_vc_lsn = -1;
|
|
||||||
|
|
||||||
//new nxdn stuff
|
//new nxdn stuff
|
||||||
state->nxdn_part_of_frame = 0;
|
state->nxdn_part_of_frame = 0;
|
||||||
@@ -795,7 +818,10 @@ initState (dsd_state * state)
|
|||||||
//site/srv/cch info
|
//site/srv/cch info
|
||||||
state->nxdn_location_site_code = 0;
|
state->nxdn_location_site_code = 0;
|
||||||
state->nxdn_location_sys_code = 0;
|
state->nxdn_location_sys_code = 0;
|
||||||
sprintf (state->nxdn_location_category, "%s", " ");
|
sprintf (state->nxdn_location_category, "%s", " ");
|
||||||
|
|
||||||
|
//multi-key array
|
||||||
|
memset (state->rkey_array, 0, sizeof(state->rkey_array));
|
||||||
|
|
||||||
//Remus DMR End Call Alert Beep
|
//Remus DMR End Call Alert Beep
|
||||||
state->dmr_end_alert[0] = 0;
|
state->dmr_end_alert[0] = 0;
|
||||||
@@ -807,6 +833,7 @@ initState (dsd_state * state)
|
|||||||
|
|
||||||
//initialize unified dmr pdu 'superframe'
|
//initialize unified dmr pdu 'superframe'
|
||||||
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
|
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
|
||||||
|
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
|
||||||
|
|
||||||
//init confirmed data individual block crc as invalid
|
//init confirmed data individual block crc as invalid
|
||||||
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
|
||||||
@@ -826,14 +853,23 @@ initState (dsd_state * state)
|
|||||||
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
|
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
|
||||||
|
|
||||||
//REMUS! multi-purpose call_string
|
//REMUS! multi-purpose call_string
|
||||||
sprintf (state->call_string[0], "%s", " "); //20 spaces
|
sprintf (state->call_string[0], "%s", " "); //21 spaces
|
||||||
sprintf (state->call_string[1], "%s", " "); //20 spaces
|
sprintf (state->call_string[1], "%s", " "); //21 spaces
|
||||||
|
|
||||||
//late entry mi fragments
|
//late entry mi fragments
|
||||||
memset (state->late_entry_mi_fragment, 0, sizeof (state->late_entry_mi_fragment));
|
memset (state->late_entry_mi_fragment, 0, sizeof (state->late_entry_mi_fragment));
|
||||||
|
|
||||||
initialize_p25_heuristics(&state->p25_heuristics);
|
initialize_p25_heuristics(&state->p25_heuristics);
|
||||||
|
|
||||||
|
state->dPMRVoiceFS2Frame.CalledIDOk = 0;
|
||||||
|
state->dPMRVoiceFS2Frame.CallingIDOk = 0;
|
||||||
|
memset(state->dPMRVoiceFS2Frame.CalledID, 0, 8);
|
||||||
|
memset(state->dPMRVoiceFS2Frame.CallingID, 0, 8);
|
||||||
|
memset(state->dPMRVoiceFS2Frame.Version, 0, 8);
|
||||||
|
|
||||||
|
sprintf (state->dpmr_caller_id, "%s", " ");
|
||||||
|
sprintf (state->dpmr_target_id, "%s", " ");
|
||||||
|
|
||||||
} //init_state
|
} //init_state
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -865,7 +901,7 @@ usage ()
|
|||||||
printf (" -o <device> Audio output device (default is /dev/dsp)\n");
|
printf (" -o <device> Audio output device (default is /dev/dsp)\n");
|
||||||
printf (" null for no audio output\n");
|
printf (" null for no audio output\n");
|
||||||
printf (" pulse for pulse audio \n");
|
printf (" pulse for pulse audio \n");
|
||||||
printf (" -d <dir> Create mbe data files, use this directory\n");
|
printf (" -d <dir> Create mbe data files, use this directory (TDMA version is experimental)\n");
|
||||||
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
|
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
|
||||||
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
|
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
|
||||||
printf (" -w <file> Output synthesized speech to a .wav file, legacy auto modes only.\n");
|
printf (" -w <file> Output synthesized speech to a .wav file, legacy auto modes only.\n");
|
||||||
@@ -875,6 +911,7 @@ usage ()
|
|||||||
printf (" -a Enable Call Alert Beep (NCurses Terminal Only)\n");
|
printf (" -a Enable Call Alert Beep (NCurses Terminal Only)\n");
|
||||||
printf (" (Warning! Might be annoying.)\n");
|
printf (" (Warning! Might be annoying.)\n");
|
||||||
printf (" -L <file> Specify Filename for LRRP Data Output.\n");
|
printf (" -L <file> Specify Filename for LRRP Data Output.\n");
|
||||||
|
printf (" -Q <file> Specify Filename for DSP Structured File Output. (placed in DSP folder)\n");
|
||||||
printf (" -c <file> Output symbol capture to .bin file\n");
|
printf (" -c <file> Output symbol capture to .bin file\n");
|
||||||
printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n");
|
printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n");
|
||||||
printf (" -V Enable Audio Smoothing on Upsampled 48k/1 or 24k/2 Audio (Capital V)\n");
|
printf (" -V Enable Audio Smoothing on Upsampled 48k/1 or 24k/2 Audio (Capital V)\n");
|
||||||
@@ -894,9 +931,9 @@ usage ()
|
|||||||
printf (" Example: dsd-fme-lite -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
|
printf (" Example: dsd-fme-lite -fp -i rtl:0:851.375M:22:-2:12:0:6021\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("Decoder options:\n");
|
printf ("Decoder options:\n");
|
||||||
printf (" -fa Legacy Auto Detection 8k/1 (old methods default)\n");
|
printf (" -fa Legacy Auto Detection (old methods default)\n");
|
||||||
printf (" -ft XDMA P25 and DMR BS/MS frame types (new default)\n");
|
printf (" -ft XDMA P25 and DMR BS/MS frame types (new default)\n");
|
||||||
printf (" -fs DMR Stereo BS and MS Simplex only\n");
|
printf (" -fs DMR Stereo BS and MS Simplex\n");
|
||||||
printf (" -f1 Decode only P25 Phase 1\n");
|
printf (" -f1 Decode only P25 Phase 1\n");
|
||||||
printf (" -fd Decode only D-STAR\n");
|
printf (" -fd Decode only D-STAR\n");
|
||||||
printf (" -fr Decode only DMR Mono - Single Slot Voice\n");
|
printf (" -fr Decode only DMR Mono - Single Slot Voice\n");
|
||||||
@@ -905,7 +942,7 @@ usage ()
|
|||||||
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
|
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
|
||||||
printf (" -fp Decode only EDACS/ProVoice*\n");
|
printf (" -fp Decode only EDACS/ProVoice*\n");
|
||||||
printf (" -fm Decode only dPMR*\n");
|
printf (" -fm Decode only dPMR*\n");
|
||||||
printf (" -l Disable DMR and NXDN input filtering\n");
|
printf (" -l Disable DMR, dPMR, and NXDN input filtering\n");
|
||||||
printf (" -u <num> Unvoiced speech quality (default=3)\n");
|
printf (" -u <num> Unvoiced speech quality (default=3)\n");
|
||||||
printf (" -xx Expect non-inverted X2-TDMA signal\n");
|
printf (" -xx Expect non-inverted X2-TDMA signal\n");
|
||||||
printf (" -xr Expect inverted DMR signal\n");
|
printf (" -xr Expect inverted DMR signal\n");
|
||||||
@@ -933,9 +970,8 @@ usage ()
|
|||||||
//printf (" (4 Level, not 8 Level LSM) (this is honestly unknown since I can't verify what local systems are using)\n");
|
//printf (" (4 Level, not 8 Level LSM) (this is honestly unknown since I can't verify what local systems are using)\n");
|
||||||
printf (" -F Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
|
printf (" -F Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
|
||||||
printf (" Use this feature to allow MAC_SIGNAL even if CRC errors.\n");
|
printf (" Use this feature to allow MAC_SIGNAL even if CRC errors.\n");
|
||||||
printf (" -F Relax DMR CACH/Burst FEC Pass/Fail - Passive Frame Sync\n");
|
printf (" -F Relax DMR CACH/Burst FEC or RAS/CRC CSBK Pass/Fail\n");
|
||||||
printf (" Use if skipping occurs, but may cause wonky audio due to loss of good sync\n");
|
printf (" Enabling on some systems could lead to bad voice/data decoding if bad or marginal signal\n");
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf (" -K <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
|
printf (" -K <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
@@ -945,7 +981,8 @@ usage ()
|
|||||||
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
|
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
|
||||||
printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n");
|
printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf (" -R <dec> Manually Enter NXDN 4800/9600 EHR Scrambler Key Value (Decimal Value)\n");
|
printf (" -R <dec> Manually Enter dPMR or NXDN EHR Scrambler Key Value (Decimal Value)\n");
|
||||||
|
printf (" -k <file> Import NXDN Scrambler Key List from csv file.\n");
|
||||||
printf (" \n");
|
printf (" \n");
|
||||||
printf (" -4 Force Privacy Key over FID and SVC bits \n");
|
printf (" -4 Force Privacy Key over FID and SVC bits \n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
@@ -1027,6 +1064,7 @@ if (opts->audio_in_type == 0)
|
|||||||
|
|
||||||
if (opts->audio_out_type == 0)
|
if (opts->audio_out_type == 0)
|
||||||
{
|
{
|
||||||
|
// openPulseInput(opts); //test to see if we still randomly hang up in ncurses and tcp input if we open this and leave it opened
|
||||||
openPulseOutput(opts);
|
openPulseOutput(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1096,10 +1134,10 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
closeSymbolOutFile (opts, state);
|
closeSymbolOutFile (opts, state);
|
||||||
}
|
}
|
||||||
if (opts->mbe_out_f != NULL)
|
|
||||||
{
|
//close MBE out files
|
||||||
closeMbeOutFile (opts, state);
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
}
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
|
||||||
fprintf (stderr,"\n");
|
fprintf (stderr,"\n");
|
||||||
fprintf (stderr,"Total audio errors: %i\n", state->debug_audio_errors);
|
fprintf (stderr,"Total audio errors: %i\n", state->debug_audio_errors);
|
||||||
@@ -1181,7 +1219,7 @@ main (int argc, char **argv)
|
|||||||
exitflag = 0;
|
exitflag = 0;
|
||||||
// signal (SIGINT, sigfun);
|
// signal (SIGINT, sigfun);
|
||||||
|
|
||||||
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQWrlZTF01:2:345:6:7:89:E")) != -1)
|
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
|
||||||
{
|
{
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
switch (c)
|
switch (c)
|
||||||
@@ -1199,6 +1237,29 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
//Disabled the Serial Port Dev and Baud Rate, etc, If somebody uses that function, sorry...
|
//Disabled the Serial Port Dev and Baud Rate, etc, If somebody uses that function, sorry...
|
||||||
|
|
||||||
|
case 'k': //NXDN multi-key loader
|
||||||
|
strncpy(opts.key_in_file, optarg, 1023);
|
||||||
|
opts.key_in_file[1023] = '\0';
|
||||||
|
csvKeyImport(&opts, &state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Q': //'DSP' Structured Output file for OKDMRlib
|
||||||
|
sprintf (wav_file_directory, "./DSP");
|
||||||
|
wav_file_directory[1023] = '\0';
|
||||||
|
if (stat(wav_file_directory, &st) == -1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "-Q %s DSP file directory does not exist\n", wav_file_directory);
|
||||||
|
fprintf (stderr, "Creating directory %s to save DSP Structured files\n", wav_file_directory);
|
||||||
|
mkdir(wav_file_directory, 0700); //user read write execute, needs execute for some reason or segfault
|
||||||
|
}
|
||||||
|
//read in filename
|
||||||
|
//sprintf (opts.wav_out_file, "./WAV/DSD-FME-X1.wav");
|
||||||
|
strncpy(dsp_filename, optarg, 1023);
|
||||||
|
sprintf(opts.dsp_out_file, "%s/%s", wav_file_directory, dsp_filename);
|
||||||
|
fprintf (stderr, "Saving DSP Structured files to %s\n", opts.dsp_out_file);
|
||||||
|
opts.use_dsp_output = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'z':
|
case 'z':
|
||||||
sscanf (optarg, "%d", &opts.slot_preference);
|
sscanf (optarg, "%d", &opts.slot_preference);
|
||||||
opts.slot_preference--; //user inputs 1 or 2, internally we want 0 and 1
|
opts.slot_preference--; //user inputs 1 or 2, internally we want 0 and 1
|
||||||
@@ -1459,7 +1520,7 @@ main (int argc, char **argv)
|
|||||||
wav_file_directory[1023] = '\0';
|
wav_file_directory[1023] = '\0';
|
||||||
if (stat(wav_file_directory, &st) == -1)
|
if (stat(wav_file_directory, &st) == -1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "-T %s WAV file directory does not exist\n", wav_file_directory);
|
fprintf (stderr, "-P %s WAV file directory does not exist\n", wav_file_directory);
|
||||||
fprintf (stderr, "Creating directory %s to save decoded wav files\n", wav_file_directory);
|
fprintf (stderr, "Creating directory %s to save decoded wav files\n", wav_file_directory);
|
||||||
mkdir(wav_file_directory, 0700); //user read write execute, needs execute for some reason or segfault
|
mkdir(wav_file_directory, 0700); //user read write execute, needs execute for some reason or segfault
|
||||||
}
|
}
|
||||||
@@ -1476,7 +1537,7 @@ main (int argc, char **argv)
|
|||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
//fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n");
|
//fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n");
|
||||||
fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
|
fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
|
||||||
fprintf (stderr, "Relax DMR CACH/Burst FEC Pass/Fail\n");
|
fprintf (stderr, "Relax DMR CACH/Burst FEC or RAS/CRC CSBK Pass/Fail\n");
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1578,10 +1639,10 @@ main (int argc, char **argv)
|
|||||||
opts.frame_dpmr = 0;
|
opts.frame_dpmr = 0;
|
||||||
opts.frame_provoice = 0;
|
opts.frame_provoice = 0;
|
||||||
opts.frame_ysf = 0;
|
opts.frame_ysf = 0;
|
||||||
opts.pulse_digi_rate_out = 8000; //doesn't matter for /dev/dsp anyways
|
opts.pulse_digi_rate_out = 48000; // /dev/dsp does need this set to 48000 to properly process the upsampling
|
||||||
opts.pulse_digi_out_channels = 1;
|
opts.pulse_digi_out_channels = 1;
|
||||||
opts.dmr_stereo = 0;
|
opts.dmr_stereo = 1; //switching in 'stereo' for 'mono'
|
||||||
opts.dmr_mono = 1;
|
opts.dmr_mono = 0;
|
||||||
state.dmr_stereo = 0;
|
state.dmr_stereo = 0;
|
||||||
opts.setmod_bw = 7000;
|
opts.setmod_bw = 7000;
|
||||||
sprintf (opts.output_name, "Legacy Auto");
|
sprintf (opts.output_name, "Legacy Auto");
|
||||||
@@ -1864,7 +1925,7 @@ main (int argc, char **argv)
|
|||||||
opts.setmod_bw = 7000;
|
opts.setmod_bw = 7000;
|
||||||
sprintf (opts.output_name, "DMR Mono");
|
sprintf (opts.output_name, "DMR Mono");
|
||||||
//fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
|
//fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
|
||||||
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo or XDMA is highly encouraged.\n");
|
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo '-fs' or XDMA '-ft' is highly encouraged.\n");
|
||||||
//dmr stereo below
|
//dmr stereo below
|
||||||
// opts.frame_dstar = 0;
|
// opts.frame_dstar = 0;
|
||||||
// opts.frame_x2tdma = 0;
|
// opts.frame_x2tdma = 0;
|
||||||
@@ -2318,13 +2379,13 @@ main (int argc, char **argv)
|
|||||||
opts.playoffsetR = 0;
|
opts.playoffsetR = 0;
|
||||||
opts.delay = 0;
|
opts.delay = 0;
|
||||||
if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
|
if (strlen(opts.wav_out_file) > 0 && opts.dmr_stereo_wav == 0)
|
||||||
{
|
{
|
||||||
openWavOutFile (&opts, &state);
|
openWavOutFile (&opts, &state);
|
||||||
}
|
}
|
||||||
else
|
opts.pulse_digi_rate_out = 48000;
|
||||||
{
|
opts.pulse_digi_out_channels = 1;
|
||||||
openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
|
if (opts.audio_out_type == 0) openPulseOutput(&opts); //need to open it up for output?
|
||||||
}
|
if (opts.audio_out_type == 5) openAudioOutDevice (&opts, SAMPLE_RATE_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
|
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
|
||||||
@@ -2359,10 +2420,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
if (opts.playfiles == 1)
|
if (opts.playfiles == 1)
|
||||||
{
|
{
|
||||||
opts.pulse_digi_rate_out = 48000;
|
state.aout_gain = 25; //BUGFIX: No audio output when playing back .amb/.imb files
|
||||||
opts.pulse_digi_out_channels = 1;
|
|
||||||
// openPulseOutput(&opts); //need to open it up for output?
|
|
||||||
openAudioInDevice (&opts); //needs to be tested, not sure if required
|
|
||||||
playMbeFiles (&opts, &state, argc, argv);
|
playMbeFiles (&opts, &state, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
197
src/dsd_mbe.c
197
src/dsd_mbe.c
@@ -17,8 +17,42 @@
|
|||||||
|
|
||||||
#include "dsd.h"
|
#include "dsd.h"
|
||||||
|
|
||||||
void
|
int Pr[256] = {
|
||||||
playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
|
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
|
||||||
|
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
|
||||||
|
0x2618, 0x3918, 0xC518, 0xDA18, 0x031B, 0x1C1B, 0xE01B, 0xFF1B,
|
||||||
|
0x6C1D, 0x731D, 0x8F1D, 0x901D, 0x491E, 0x561E, 0xAA1E, 0xB51E, //31
|
||||||
|
0x4B28, 0x5428, 0xA828, 0xB728, 0x6E2B, 0x712B, 0x8D2B, 0x922B,
|
||||||
|
0x012D, 0x1E2D, 0xE22D, 0xFD2D, 0x242E, 0x3B2E, 0xC72E, 0xD82E,
|
||||||
|
0x6D30, 0x7230, 0x8E30, 0x9130, 0x4833, 0x5733, 0xAB33, 0xB433,
|
||||||
|
0x2735, 0x3835, 0xC435, 0xDB35, 0x0236, 0x1D36, 0xE136, 0xFE36, //63
|
||||||
|
0x2B49, 0x3449, 0xC849, 0xD749, 0x0E4A, 0x114A, 0xED4A, 0xF24A,
|
||||||
|
0x614C, 0xAE4C, 0x824C, 0x9D4C, 0x444F, 0x5B4F, 0xA74F, 0xB84F,
|
||||||
|
0x0D51, 0x1251, 0xEE51, 0xF151, 0x2852, 0x3752, 0xCB52, 0xD452,
|
||||||
|
0x4754, 0x5854, 0xA454, 0xBB54, 0x6257, 0x7D57, 0x8157, 0x9E57, //95
|
||||||
|
0x6061, 0x7F61, 0x8361, 0x9C61, 0x4562, 0x5A62, 0xA662, 0xB962,
|
||||||
|
0x2A64, 0x3564, 0xC964, 0xD664, 0x0F67, 0x1067, 0xEC67, 0xF367,
|
||||||
|
0x4679, 0x5979, 0xA579, 0xBA79, 0x637A, 0x7C7A, 0x807A, 0x9F7A,
|
||||||
|
0x0C7C, 0x137C, 0xEF7C, 0xF07C, 0x297F, 0x367F, 0xCA7F, 0xD57F, //127
|
||||||
|
0x4D89, 0x5289, 0xAE89, 0xB189, 0x688A, 0x778A, 0x8B8A, 0x948A,
|
||||||
|
0x078C, 0x188C, 0xE48C, 0xFB8C, 0x228F, 0x3D8F, 0xC18F, 0xDE8F,
|
||||||
|
0x6B91, 0x7491, 0x8891, 0x9791, 0x4E92, 0x5192, 0xAD92, 0xB292,
|
||||||
|
0x2194, 0x3E94, 0xC294, 0xDD94, 0x0497, 0x1B97, 0xE797, 0xF897, //159
|
||||||
|
0x06A1, 0x19A1, 0xE5A1, 0xFAA1, 0x23A2, 0x3CA2, 0xC0A2, 0xDFA2,
|
||||||
|
0x4CA4, 0x53A4, 0xAFA4, 0xB0A4, 0x69A7, 0x76A7, 0x8AA7, 0x95A7,
|
||||||
|
0x20B9, 0x3FB9, 0xC3B9, 0xDCB9, 0x05BA, 0x1ABA, 0xE6BA, 0xF9BA,
|
||||||
|
0x6ABC, 0x75BC, 0x89BC, 0x96BC, 0x4FBF, 0x50BF, 0xACBF, 0xB3BF, //191
|
||||||
|
0x66C0, 0x79C0, 0x85C0, 0x9AC0, 0x43C3, 0x5CC3, 0xA0C3, 0xBFC3,
|
||||||
|
0x2CC5, 0x33C5, 0xCFC5, 0xD0C5, 0x09C6, 0x16C6, 0xEAC6, 0xF5C6,
|
||||||
|
0x84D0, 0x85DF, 0x8AD3, 0x8BDC, 0xB6D5, 0xB7DA, 0xB8D6, 0xB9D9,
|
||||||
|
0xD0DA, 0xD1D5, 0xDED9, 0xDFD6, 0xE2DF, 0xE3D0, 0xECDC, 0xEDD3, //223
|
||||||
|
0x2DE8, 0x32E8, 0xCEE8, 0xD1E8, 0x08EB, 0x17EB, 0xEBEB, 0xF4EB,
|
||||||
|
0x67ED, 0x78ED, 0x84ED, 0x9BED, 0x42EE, 0x5DEE, 0xA1EE, 0xBEEE,
|
||||||
|
0x0BF0, 0x14F0, 0xE8F0, 0xF7F0, 0x2EF3, 0x31F3, 0xCDF3, 0xD2F3,
|
||||||
|
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255
|
||||||
|
};
|
||||||
|
|
||||||
|
void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@@ -26,99 +60,79 @@ playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
|
|||||||
char ambe_d[49];
|
char ambe_d[49];
|
||||||
|
|
||||||
for (i = state->optind; i < argc; i++)
|
for (i = state->optind; i < argc; i++)
|
||||||
|
{
|
||||||
|
sprintf (opts->mbe_in_file, "%s", argv[i]);
|
||||||
|
openMbeInFile (opts, state);
|
||||||
|
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
||||||
|
fprintf (stderr, "playing %s\n", opts->mbe_in_file);
|
||||||
|
while (feof (opts->mbe_in_f) == 0)
|
||||||
{
|
{
|
||||||
sprintf (opts->mbe_in_file, "%s", argv[i]);
|
if (state->mbe_file_type == 0)
|
||||||
openMbeInFile (opts, state);
|
{
|
||||||
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
readImbe4400Data (opts, state, imbe_d);
|
||||||
fprintf (stderr, "playing %s\n", opts->mbe_in_file);
|
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||||
while (feof (opts->mbe_in_f) == 0)
|
if (opts->audio_out == 1)
|
||||||
{
|
{
|
||||||
if (state->mbe_file_type == 0)
|
processAudio(opts, state);
|
||||||
{
|
|
||||||
readImbe4400Data (opts, state, imbe_d);
|
|
||||||
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
||||||
if (opts->audio_out == 1)
|
|
||||||
{
|
|
||||||
processAudio(opts, state);
|
|
||||||
}
|
|
||||||
if (opts->wav_out_f != NULL)
|
|
||||||
{
|
|
||||||
writeSynthesizedVoice (opts, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts->audio_out == 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
playSynthesizedVoice (opts, state);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (state->mbe_file_type == 1)
|
|
||||||
{
|
|
||||||
readAmbe2450Data (opts, state, ambe_d);
|
|
||||||
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
||||||
if (opts->audio_out == 1)
|
|
||||||
{
|
|
||||||
processAudio(opts, state);
|
|
||||||
}
|
|
||||||
if (opts->wav_out_f != NULL)
|
|
||||||
{
|
|
||||||
writeSynthesizedVoice (opts, state);
|
|
||||||
}
|
|
||||||
if (opts->audio_out == 1)
|
|
||||||
{
|
|
||||||
playSynthesizedVoice (opts, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exitflag == 1)
|
|
||||||
{
|
|
||||||
cleanupAndExit (opts, state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (opts->wav_out_f != NULL)
|
||||||
|
{
|
||||||
|
writeSynthesizedVoice (opts, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->audio_out == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
playSynthesizedVoice (opts, state);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state->mbe_file_type > 0) //ambe files
|
||||||
|
{
|
||||||
|
readAmbe2450Data (opts, state, ambe_d);
|
||||||
|
int j, x;
|
||||||
|
unsigned long long int k;
|
||||||
|
if (state->K != 0) //apply Pr key
|
||||||
|
{
|
||||||
|
k = Pr[state->K];
|
||||||
|
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
||||||
|
for (short int j = 0; j < 48; j++) //49
|
||||||
|
{
|
||||||
|
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||||
|
ambe_d[j] ^= x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ambe+2
|
||||||
|
if (state->mbe_file_type == 1) mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||||
|
//dstar ambe
|
||||||
|
if (state->mbe_file_type == 2) mbe_processAmbe2400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||||
|
|
||||||
|
if (opts->audio_out == 1)
|
||||||
|
{
|
||||||
|
processAudio(opts, state);
|
||||||
|
}
|
||||||
|
if (opts->wav_out_f != NULL)
|
||||||
|
{
|
||||||
|
writeSynthesizedVoice (opts, state);
|
||||||
|
}
|
||||||
|
if (opts->audio_out == 1)
|
||||||
|
{
|
||||||
|
playSynthesizedVoice (opts, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exitflag == 1)
|
||||||
|
{
|
||||||
|
cleanupAndExit (opts, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24])
|
processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24])
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
|
||||||
int Pr[256] = {
|
|
||||||
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
|
|
||||||
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
|
|
||||||
0x2618, 0x3918, 0xC518, 0xDA18, 0x031B, 0x1C1B, 0xE01B, 0xFF1B,
|
|
||||||
0x6C1D, 0x731D, 0x8F1D, 0x901D, 0x491E, 0x561E, 0xAA1E, 0xB51E, //31
|
|
||||||
0x4B28, 0x5428, 0xA828, 0xB728, 0x6E2B, 0x712B, 0x8D2B, 0x922B,
|
|
||||||
0x012D, 0x1E2D, 0xE22D, 0xFD2D, 0x242E, 0x3B2E, 0xC72E, 0xD82E,
|
|
||||||
0x6D30, 0x7230, 0x8E30, 0x9130, 0x4833, 0x5733, 0xAB33, 0xB433,
|
|
||||||
0x2735, 0x3835, 0xC435, 0xDB35, 0x0236, 0x1D36, 0xE136, 0xFE36, //63
|
|
||||||
0x2B49, 0x3449, 0xC849, 0xD749, 0x0E4A, 0x114A, 0xED4A, 0xF24A,
|
|
||||||
0x614C, 0xAE4C, 0x824C, 0x9D4C, 0x444F, 0x5B4F, 0xA74F, 0xB84F,
|
|
||||||
0x0D51, 0x1251, 0xEE51, 0xF151, 0x2852, 0x3752, 0xCB52, 0xD452,
|
|
||||||
0x4754, 0x5854, 0xA454, 0xBB54, 0x6257, 0x7D57, 0x8157, 0x9E57, //95
|
|
||||||
0x6061, 0x7F61, 0x8361, 0x9C61, 0x4562, 0x5A62, 0xA662, 0xB962,
|
|
||||||
0x2A64, 0x3564, 0xC964, 0xD664, 0x0F67, 0x1067, 0xEC67, 0xF367,
|
|
||||||
0x4679, 0x5979, 0xA579, 0xBA79, 0x637A, 0x7C7A, 0x807A, 0x9F7A,
|
|
||||||
0x0C7C, 0x137C, 0xEF7C, 0xF07C, 0x297F, 0x367F, 0xCA7F, 0xD57F, //127
|
|
||||||
0x4D89, 0x5289, 0xAE89, 0xB189, 0x688A, 0x778A, 0x8B8A, 0x948A,
|
|
||||||
0x078C, 0x188C, 0xE48C, 0xFB8C, 0x228F, 0x3D8F, 0xC18F, 0xDE8F,
|
|
||||||
0x6B91, 0x7491, 0x8891, 0x9791, 0x4E92, 0x5192, 0xAD92, 0xB292,
|
|
||||||
0x2194, 0x3E94, 0xC294, 0xDD94, 0x0497, 0x1B97, 0xE797, 0xF897, //159
|
|
||||||
0x06A1, 0x19A1, 0xE5A1, 0xFAA1, 0x23A2, 0x3CA2, 0xC0A2, 0xDFA2,
|
|
||||||
0x4CA4, 0x53A4, 0xAFA4, 0xB0A4, 0x69A7, 0x76A7, 0x8AA7, 0x95A7,
|
|
||||||
0x20B9, 0x3FB9, 0xC3B9, 0xDCB9, 0x05BA, 0x1ABA, 0xE6BA, 0xF9BA,
|
|
||||||
0x6ABC, 0x75BC, 0x89BC, 0x96BC, 0x4FBF, 0x50BF, 0xACBF, 0xB3BF, //191
|
|
||||||
0x66C0, 0x79C0, 0x85C0, 0x9AC0, 0x43C3, 0x5CC3, 0xA0C3, 0xBFC3,
|
|
||||||
0x2CC5, 0x33C5, 0xCFC5, 0xD0C5, 0x09C6, 0x16C6, 0xEAC6, 0xF5C6,
|
|
||||||
0x84D0, 0x85DF, 0x8AD3, 0x8BDC, 0xB6D5, 0xB7DA, 0xB8D6, 0xB9D9,
|
|
||||||
0xD0DA, 0xD1D5, 0xDED9, 0xDFD6, 0xE2DF, 0xE3D0, 0xECDC, 0xEDD3, //223
|
|
||||||
0x2DE8, 0x32E8, 0xCEE8, 0xD1E8, 0x08EB, 0x17EB, 0xEBEB, 0xF4EB,
|
|
||||||
0x67ED, 0x78ED, 0x84ED, 0x9BED, 0x42EE, 0x5DEE, 0xA1EE, 0xBEEE,
|
|
||||||
0x0BF0, 0x14F0, 0xE8F0, 0xF7F0, 0x2EF3, 0x31F3, 0xCDF3, 0xD2F3,
|
|
||||||
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255
|
|
||||||
};
|
|
||||||
//
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char imbe_d[88];
|
char imbe_d[88];
|
||||||
char ambe_d[49];
|
char ambe_d[49];
|
||||||
@@ -364,6 +378,13 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
{
|
{
|
||||||
PrintAMBEData (opts, state, ambe_d);
|
PrintAMBEData (opts, state, ambe_d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//restore MBE file save, slot 1 -- consider saving even if enc
|
||||||
|
if (opts->mbe_out_f != NULL && (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) )
|
||||||
|
{
|
||||||
|
saveAmbe2450Data (opts, state, ambe_d);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//stereo slots and slot 1 (right slot)
|
//stereo slots and slot 1 (right slot)
|
||||||
if (state->currentslot == 1) //&& opts->dmr_stereo == 1
|
if (state->currentslot == 1) //&& opts->dmr_stereo == 1
|
||||||
@@ -458,6 +479,12 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
{
|
{
|
||||||
PrintAMBEData (opts, state, ambe_d);
|
PrintAMBEData (opts, state, ambe_d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//restore MBE file save, slot 2 -- consider saving even if enc
|
||||||
|
if (opts->mbe_out_fR != NULL && (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) )
|
||||||
|
{
|
||||||
|
saveAmbe2450DataR (opts, state, ambe_d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//X2-TDMA? Not sure what still makes it this far to run under Framef
|
//X2-TDMA? Not sure what still makes it this far to run under Framef
|
||||||
|
|||||||
@@ -840,8 +840,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
|||||||
if(opts->tcp_file_in == NULL)
|
if(opts->tcp_file_in == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
|
fprintf(stderr, "Error, couldn't open TCP with libsndfile: %s\n", sf_strerror(NULL));
|
||||||
sprintf (opts->audio_in_dev, "%s", "pulse");
|
if (opts->audio_out_type == 0)
|
||||||
opts->audio_in_type = 0;
|
{
|
||||||
|
sprintf (opts->audio_in_dev, "%s", "pulse");
|
||||||
|
opts->audio_in_type = 0;
|
||||||
|
}
|
||||||
|
else opts->audio_in_type = 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
|
state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
|
||||||
@@ -971,7 +976,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
opts->audio_in_type = 0; //set after closing to prevent above crash condition
|
if (opts->audio_out_type == 0) opts->audio_in_type = 0; //set after closing to prevent above crash condition
|
||||||
|
else (opts->audio_in_type = 5);
|
||||||
|
|
||||||
choicec = 18; //exit
|
choicec = 18; //exit
|
||||||
}
|
}
|
||||||
@@ -1045,7 +1051,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
|||||||
mvwprintw(entry_win, 3, 2, " ");
|
mvwprintw(entry_win, 3, 2, " ");
|
||||||
mvwprintw(entry_win, 4, 2, "1 - Basic Privacy ");
|
mvwprintw(entry_win, 4, 2, "1 - Basic Privacy ");
|
||||||
mvwprintw(entry_win, 5, 2, "2 - **tera Privacy ");
|
mvwprintw(entry_win, 5, 2, "2 - **tera Privacy ");
|
||||||
mvwprintw(entry_win, 6, 2, "3 - NXDN Scrambler ");
|
mvwprintw(entry_win, 6, 2, "3 - NXDN/dPMR Scrambler ");
|
||||||
mvwprintw(entry_win, 7, 2, "4 - Force Key Priority ");
|
mvwprintw(entry_win, 7, 2, "4 - Force Key Priority ");
|
||||||
mvwprintw(entry_win, 8, 3, " ");
|
mvwprintw(entry_win, 8, 3, " ");
|
||||||
echo();
|
echo();
|
||||||
@@ -1125,7 +1131,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
|||||||
state->R = 0;
|
state->R = 0;
|
||||||
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
||||||
box (entry_win, 0, 0);
|
box (entry_win, 0, 0);
|
||||||
mvwprintw(entry_win, 2, 2, "NXDN Scrambler Key Value (DEC):");
|
mvwprintw(entry_win, 2, 2, "NXDN/dPMR Scrambler Key Value (DEC):");
|
||||||
mvwprintw(entry_win, 3, 3, " ");
|
mvwprintw(entry_win, 3, 3, " ");
|
||||||
echo();
|
echo();
|
||||||
refresh();
|
refresh();
|
||||||
@@ -1684,35 +1690,21 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
|
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
|
||||||
{
|
{
|
||||||
timeout(0);
|
timeout(0); //
|
||||||
c = getch();
|
c = getch(); //
|
||||||
}
|
}
|
||||||
|
|
||||||
//testing sending UDP commands to the socket inside of rtl_sdr_fm.cpp
|
//use rtl_udp_tune
|
||||||
//this works, but we will want to make an init func open one time, and have sendto here
|
|
||||||
#ifdef USE_RTLSDR
|
#ifdef USE_RTLSDR
|
||||||
if (temp_freq == opts->rtlsdr_center_freq)
|
if (temp_freq == opts->rtlsdr_center_freq)
|
||||||
{
|
{
|
||||||
handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
rtl_udp_tune (opts, state, temp_freq);
|
||||||
|
|
||||||
memset((char * ) & address, 0, sizeof(address));
|
|
||||||
address.sin_family = AF_INET;
|
|
||||||
address.sin_addr.s_addr = inet_addr(SRV_IP); //address of host
|
|
||||||
address.sin_port = htons(udp_port);
|
|
||||||
sendto(handle, data, UDP_BUFLEN, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
|
|
||||||
|
|
||||||
temp_freq = -1;
|
temp_freq = -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Variable reset/set section
|
//Variable reset/set section
|
||||||
|
|
||||||
//carrier reset
|
|
||||||
// if (state->carrier == 0) //reset these to 0 when no carrier
|
|
||||||
// {
|
|
||||||
// sprintf(state->dmr_branding, "%s", "");
|
|
||||||
// }
|
|
||||||
|
|
||||||
//set lls sync types
|
//set lls sync types
|
||||||
if (state->synctype >= 0 && state->synctype < 39)
|
if (state->synctype >= 0 && state->synctype < 39)
|
||||||
{
|
{
|
||||||
@@ -1908,7 +1900,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1 && rd != 0 && tg != 0)
|
||||||
{
|
{
|
||||||
//fprintf (stderr, "BEEP 0 MS LEFT\n");
|
//fprintf (stderr, "BEEP 0 MS LEFT\n");
|
||||||
beeper (opts, state, 0);
|
beeper (opts, state, 0);
|
||||||
@@ -1951,7 +1943,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1 && rd != 0 && tg != 0)
|
||||||
{
|
{
|
||||||
//fprintf (stderr, "BEEP 0 BS LEFT\n");
|
//fprintf (stderr, "BEEP 0 BS LEFT\n");
|
||||||
beeper (opts, state, 0);
|
beeper (opts, state, 0);
|
||||||
@@ -1993,7 +1985,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
openWavOutFileR (opts, state); //testing for now, will want to move to per call later
|
openWavOutFileR (opts, state); //testing for now, will want to move to per call later
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1 && rdR != 0 && tgR != 0)
|
||||||
{
|
{
|
||||||
//fprintf (stderr, "BEEP 1 BS RIGHT\n");
|
//fprintf (stderr, "BEEP 1 BS RIGHT\n");
|
||||||
beeper (opts, state, 1);
|
beeper (opts, state, 1);
|
||||||
@@ -2048,11 +2040,19 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
// {
|
// {
|
||||||
// beeper (opts, state, 0);
|
// beeper (opts, state, 0);
|
||||||
// state->dmr_end_alert[0] = 1; //don't play again until new voice frames
|
// state->dmr_end_alert[0] = 1; //don't play again until new voice frames
|
||||||
|
// state->lasttg = 0;
|
||||||
|
// state->lastsrc = 0;
|
||||||
|
// rd = 0;
|
||||||
|
// tg = 0;
|
||||||
// }
|
// }
|
||||||
// if (state->dmrburstR == 2 && state->dmr_end_alert[1] == 0) //if TLC and flag not tripped
|
// if (state->dmrburstR == 2 && state->dmr_end_alert[1] == 0) //if TLC and flag not tripped
|
||||||
// {
|
// {
|
||||||
// beeper (opts, state, 1);
|
// beeper (opts, state, 1);
|
||||||
// state->dmr_end_alert[1] = 1; //don't play again until new voice frames
|
// state->dmr_end_alert[1] = 1; //don't play again until new voice frames
|
||||||
|
// state->lasttgR = 0;
|
||||||
|
// state->lastsrcR = 0;
|
||||||
|
// rdR = 0;
|
||||||
|
// tgR = 0;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -2061,7 +2061,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
if (opts->ncurses_compact == 1)
|
if (opts->ncurses_compact == 1)
|
||||||
{
|
{
|
||||||
printw ("------------------------------------------------------------------------------\n");
|
printw ("------------------------------------------------------------------------------\n");
|
||||||
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-6-gc44e039 RC1");
|
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-28-ga02f992 RC3");
|
||||||
}
|
}
|
||||||
if (opts->ncurses_compact == 0)
|
if (opts->ncurses_compact == 0)
|
||||||
{
|
{
|
||||||
@@ -2072,8 +2072,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
if (i == 1) printw (" ESC to Menu");
|
if (i == 1) printw (" ESC to Menu");
|
||||||
if (i == 2) printw (" 'q' to Quit ");
|
if (i == 2) printw (" 'q' to Quit ");
|
||||||
if (i == 4) printw (" MBElib %s", versionstr);
|
if (i == 4) printw (" MBElib %s", versionstr);
|
||||||
if (i == 5) printw (" %s ", "Win32 RC1"); //printw (" %s \n", GIT_TAG);
|
if (i == 5) printw (" %s ", "Win32 RC3"); //printw (" %s \n", GIT_TAG);
|
||||||
if (i == 6) printw (" %s \n", "v2.0.0-6-gc44e039"); //printw (" %s \n", GIT_TAG);
|
if (i == 6) printw (" %s \n", "v2.0.0-28-ga02f992"); //printw (" %s \n", GIT_TAG);
|
||||||
else printw ("\n");
|
else printw ("\n");
|
||||||
}
|
}
|
||||||
attroff(COLOR_PAIR(6)); //6
|
attroff(COLOR_PAIR(6)); //6
|
||||||
@@ -2372,7 +2372,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
else if (lls == 0 || lls == 1) //P1
|
else if (lls == 0 || lls == 1) //P1
|
||||||
{
|
{
|
||||||
printw ("P25 P1 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
// printw ("P25 P1 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
||||||
|
printw ("P25 P1 - [%05llX][%03llX][%03llX] RFSS: [%llX] SITE: [%llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc, state->p2_rfssid, state->p2_siteid);
|
||||||
if (state->p25_cc_freq != 0)
|
if (state->p25_cc_freq != 0)
|
||||||
{
|
{
|
||||||
printw ("Freq: [%.06lf] MHz", (double)state->p25_cc_freq/1000000);
|
printw ("Freq: [%.06lf] MHz", (double)state->p25_cc_freq/1000000);
|
||||||
@@ -2380,7 +2381,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
else if (lls == 35 || lls == 36) //P2
|
else if (lls == 35 || lls == 36) //P2
|
||||||
{
|
{
|
||||||
printw ("P25 P2 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
// printw ("P25 P2 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
||||||
|
printw ("P25 P2 - [%05llX][%03llX][%03llX] RFSS: [%llX] SITE: [%llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc, state->p2_rfssid, state->p2_siteid);
|
||||||
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
|
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
|
||||||
{
|
{
|
||||||
attron(COLOR_PAIR(2));
|
attron(COLOR_PAIR(2));
|
||||||
@@ -2796,7 +2798,23 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)
|
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)
|
||||||
{
|
{
|
||||||
printw ("| DCC: [%i] ", state->dpmr_color_code);
|
printw ("| DCC: [%i] ", state->dpmr_color_code);
|
||||||
printw ("TID: [%s] RID: [%s] \n", state->dpmr_target_id, state->dpmr_caller_id);
|
printw ("TGT: [%s] SRC: [%s] ", state->dpmr_target_id, state->dpmr_caller_id);
|
||||||
|
printw ("\n| ");
|
||||||
|
if (state->dPMRVoiceFS2Frame.Version[0] == 3)
|
||||||
|
{
|
||||||
|
attron(COLOR_PAIR(2));
|
||||||
|
printw ("Scrambler ");
|
||||||
|
attroff(COLOR_PAIR(2));
|
||||||
|
attron(COLOR_PAIR(3));
|
||||||
|
if (state->R != 0)
|
||||||
|
{
|
||||||
|
attron(COLOR_PAIR(1));
|
||||||
|
printw ("KEY VALUE: [%05lld] ", state->R );
|
||||||
|
//printw ("SEED: [%04llX]", state->payload_miN);
|
||||||
|
attron(COLOR_PAIR(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printw ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//EDACS and ProVoice
|
//EDACS and ProVoice
|
||||||
@@ -2904,8 +2922,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
printw ("--Call History----------------------------------------------------------------\n");
|
printw ("--Call History----------------------------------------------------------------\n");
|
||||||
for (short int j = 0; j < 10; j++)
|
for (short int j = 0; j < 10; j++)
|
||||||
{
|
{
|
||||||
//only print if a valid time was assigned to the matrix, and not EDACS/PV
|
//only print if a valid time was assigned to the matrix, and not EDACS/PV, and source is not zero
|
||||||
if ( ((time(NULL) - call_matrix[9-j][5]) < 999999) && call_matrix[9-j][0] != 14 && call_matrix[9-j][0] != 15 && call_matrix[9-j][0] != 37 && call_matrix[9-j][0] != 38 )
|
if ( ((time(NULL) - call_matrix[9-j][5]) < 999999) && call_matrix[9-j][0] != 14 && call_matrix[9-j][0] != 15 && call_matrix[9-j][0] != 37 && call_matrix[9-j][0] != 38 && call_matrix[9-j][2] != 0) //
|
||||||
{
|
{
|
||||||
printw ("| %s ", SyncTypes[call_matrix[9-j][0]]);
|
printw ("| %s ", SyncTypes[call_matrix[9-j][0]]);
|
||||||
if (lls == 28 || lls == 29)
|
if (lls == 28 || lls == 29)
|
||||||
@@ -3106,21 +3124,24 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 32) //'space bar' replay last bin file (rework to do wav files too?)
|
//
|
||||||
{
|
// if (c == 32) //'space bar' replay last bin file (rework to do wav files too?)
|
||||||
struct stat stat_buf;
|
// {
|
||||||
if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
// struct stat stat_buf;
|
||||||
{
|
// if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
||||||
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
|
// {
|
||||||
goto SKIPR;
|
// fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
|
||||||
}
|
// goto SKIPR;
|
||||||
if (S_ISREG(stat_buf.st_mode))
|
// }
|
||||||
{
|
// if (S_ISREG(stat_buf.st_mode))
|
||||||
opts->symbolfile = fopen(opts->audio_in_dev, "r");
|
// {
|
||||||
opts->audio_in_type = 4; //symbol capture bin files
|
// opts->symbolfile = fopen(opts->audio_in_dev, "r");
|
||||||
}
|
// opts->audio_in_type = 4; //symbol capture bin files
|
||||||
SKIPR: ; //do nothing
|
// }
|
||||||
}
|
// SKIPR: ; //do nothing
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
if (c == 80) //'P' key - start per call wav files
|
if (c == 80) //'P' key - start per call wav files
|
||||||
{
|
{
|
||||||
@@ -3153,28 +3174,34 @@ if (c == 112) //'p' key - stop all per call wav files
|
|||||||
opts->dmr_stereo_wav = 0;
|
opts->dmr_stereo_wav = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// if (c == 115) //'s' key, stop playing wav or symbol in files
|
||||||
|
// {
|
||||||
|
// if (opts->symbolfile != NULL)
|
||||||
|
// {
|
||||||
|
// if (opts->audio_in_type == 4)
|
||||||
|
// {
|
||||||
|
// fclose(opts->symbolfile);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (c == 115) //'s' key, stop playing wav or symbol in files
|
// if (opts->audio_in_type == 2) //wav input file
|
||||||
{
|
// {
|
||||||
if (opts->symbolfile != NULL)
|
// sf_close(opts->audio_in_file);
|
||||||
{
|
// }
|
||||||
if (opts->audio_in_type == 4)
|
|
||||||
{
|
|
||||||
fclose(opts->symbolfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts->audio_in_type == 2) //wav input file
|
// if (opts->audio_out_type == 0)
|
||||||
{
|
// {
|
||||||
sf_close(opts->audio_in_file);
|
// opts->audio_in_type = 0;
|
||||||
}
|
// openPulseInput(opts);
|
||||||
|
// }
|
||||||
|
// else opts->audio_in_type = 5;//cleanupAndExit(opts, state);
|
||||||
|
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
opts->audio_in_type = 0;
|
// //Lockout bug in EDACS prevents any group from tuning when using this, not sure why yet
|
||||||
openPulseInput(opts);
|
// //WARNING! USE THESE WITH CAUTION! IF BREAKING ISSUES OBSERVED, THEN RESTART AND DON'T USE THEM!!
|
||||||
}
|
|
||||||
|
|
||||||
//Lockout bug in EDACS prevents any group from tuning when using this, not sure why yet
|
|
||||||
//WARNING! USE THESE WITH CAUTION! IF BREAKING ISSUES OBSERVED, THEN RESTART AND DON'T USE THEM!!
|
|
||||||
if (opts->frame_provoice != 1 && c == 49) //'1' key, lockout slot 1 or conventional tg from tuning/playback during session
|
if (opts->frame_provoice != 1 && c == 49) //'1' key, lockout slot 1 or conventional tg from tuning/playback during session
|
||||||
{
|
{
|
||||||
state->group_array[state->group_tally].groupNumber = state->lasttg;
|
state->group_array[state->group_tally].groupNumber = state->lasttg;
|
||||||
@@ -3237,6 +3264,38 @@ if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls
|
|||||||
else opts->trunk_tune_group_calls = 1;
|
else opts->trunk_tune_group_calls = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c == 70) //'F' key - toggle agressive sync/crc failure/ras
|
||||||
|
{
|
||||||
|
if (opts->aggressive_framesync == 0) opts->aggressive_framesync = 1;
|
||||||
|
else opts->aggressive_framesync = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 68) //'D' key - Reset DMR Site Parms/Call Strings, etc.
|
||||||
|
{
|
||||||
|
//dmr trunking/ncurses stuff
|
||||||
|
state->dmr_rest_channel = -1; //init on -1
|
||||||
|
state->dmr_mfid = -1; //
|
||||||
|
|
||||||
|
//dmr mfid branding and site parms
|
||||||
|
sprintf(state->dmr_branding_sub, "%s", "");
|
||||||
|
sprintf(state->dmr_branding, "%s", "");
|
||||||
|
sprintf (state->dmr_site_parms, "%s", "");
|
||||||
|
|
||||||
|
//DMR Location Area - DMRLA B***S***
|
||||||
|
opts->dmr_dmrla_is_set = 0;
|
||||||
|
opts->dmr_dmrla_n = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Debug/Troubleshooting Option
|
||||||
|
if (c == 90) //'Z' key - Simulate NoCarrier/No VC/CC sync to zero out more stuff (capital Z)
|
||||||
|
{
|
||||||
|
// opts->p25_is_tuned = 0;
|
||||||
|
state->last_cc_sync_time = 0;
|
||||||
|
state->last_vc_sync_time = 0;
|
||||||
|
noCarrier(opts, state);
|
||||||
|
}
|
||||||
|
|
||||||
//anything with an entry box will need the inputs and outputs stopped first
|
//anything with an entry box will need the inputs and outputs stopped first
|
||||||
//so probably just write a function to handle c input, and when c = certain values
|
//so probably just write a function to handle c input, and when c = certain values
|
||||||
//needing an entry box, then stop all of those
|
//needing an entry box, then stop all of those
|
||||||
|
|||||||
@@ -273,4 +273,9 @@ void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency)
|
|||||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //make user configurable later
|
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //make user configurable later
|
||||||
address.sin_port = htons(udp_port);
|
address.sin_port = htons(udp_port);
|
||||||
sendto(handle, data, 5, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
|
sendto(handle, data, 5, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
//BUGFIX: This was causing an indefinite number of UDP sockets to stay open on each tune request
|
||||||
|
//we open a new socket with each request, so we need to close the socket after writing to it
|
||||||
|
//this would cause the tuning to stop after x number of tune attempts (few hours? on a busy system)
|
||||||
|
close (handle); //close socket after sending.
|
||||||
}
|
}
|
||||||
@@ -312,11 +312,11 @@ void map_isch()
|
|||||||
isch_map["fb063f092"] = 127;
|
isch_map["fb063f092"] = 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long int isch_lookup (unsigned long long int isch)
|
int isch_lookup (unsigned long long int isch)
|
||||||
{
|
{
|
||||||
map_isch(); //initialize the lookup map
|
map_isch(); //initialize the lookup map
|
||||||
char s[64];
|
char s[64];
|
||||||
unsigned long long int decoded = -2; //initialize lookup to an invalid number
|
int decoded = -2; //initialize lookup to an invalid number
|
||||||
sprintf(s, "%llx", isch);
|
sprintf(s, "%llx", isch);
|
||||||
decoded = isch_map[s];
|
decoded = isch_map[s];
|
||||||
return(decoded);
|
return(decoded);
|
||||||
|
|||||||
@@ -287,6 +287,13 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
|||||||
//rigctl
|
//rigctl
|
||||||
if (opts->use_rigctl == 1)
|
if (opts->use_rigctl == 1)
|
||||||
{
|
{
|
||||||
|
//extra safeguards due to sync issues with NXDN
|
||||||
|
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
|
||||||
|
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
|
||||||
|
state->lastsynctype = -1;
|
||||||
|
state->last_cc_sync_time = time(NULL);
|
||||||
|
//
|
||||||
|
|
||||||
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
||||||
SetFreq(opts->rigctl_sockfd, freq);
|
SetFreq(opts->rigctl_sockfd, freq);
|
||||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||||
@@ -295,6 +302,13 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
|||||||
//rtl_udp
|
//rtl_udp
|
||||||
else if (opts->audio_in_type == 3)
|
else if (opts->audio_in_type == 3)
|
||||||
{
|
{
|
||||||
|
//extra safeguards due to sync issues with NXDN
|
||||||
|
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
|
||||||
|
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
|
||||||
|
state->lastsynctype = -1;
|
||||||
|
state->last_cc_sync_time = time(NULL);
|
||||||
|
//
|
||||||
|
|
||||||
rtl_udp_tune (opts, state, freq);
|
rtl_udp_tune (opts, state, freq);
|
||||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||||
opts->p25_is_tuned = 1;
|
opts->p25_is_tuned = 1;
|
||||||
@@ -653,6 +667,9 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
|||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check the rkey array for a scrambler key value
|
||||||
|
if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID];
|
||||||
|
|
||||||
if (state->nxdn_cipher_type == 0x01 && state->R > 0) //scrambler key value
|
if (state->nxdn_cipher_type == 0x01 && state->R > 0) //scrambler key value
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
|
|||||||
@@ -247,7 +247,30 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
|
|||||||
if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits);
|
if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits);
|
||||||
if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
|
if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
|
||||||
if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
|
if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
|
||||||
if (voice) nxdn_voice (opts, state, voice, dbuf);
|
if (voice)
|
||||||
|
{
|
||||||
|
//restore MBE file open here
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
|
//update last voice sync time
|
||||||
|
state->last_vc_sync_time = time(NULL);
|
||||||
|
//process voice frame
|
||||||
|
nxdn_voice (opts, state, voice, dbuf);
|
||||||
|
}
|
||||||
|
//close MBE file if no voice and its open
|
||||||
|
if (!voice)
|
||||||
|
{
|
||||||
|
if (opts->mbe_out_f != NULL)
|
||||||
|
{
|
||||||
|
if (opts->frame_nxdn96 == 1) //nxdn96 has voice and data mixed together, so we will need to do a time check first
|
||||||
|
{
|
||||||
|
if ( (time(NULL) - state->last_vc_sync_time) > 1) //test for optimal time, 1 sec should be okay
|
||||||
|
{
|
||||||
|
closeMbeOutFile (opts, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opts->frame_nxdn48 == 1) closeMbeOutFile (opts, state); //okay to close right away if nxdn48, no data/voice mixing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
END: ; //do nothing
|
END: ; //do nothing
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ int vc_counter = 0;
|
|||||||
int framing_counter = 0;
|
int framing_counter = 0;
|
||||||
|
|
||||||
unsigned long long int isch = 0;
|
unsigned long long int isch = 0;
|
||||||
unsigned long long int isch_decoded = 0;
|
int isch_decoded = -1;
|
||||||
int p2_duid[8] = {0};
|
int p2_duid[8] = {0};
|
||||||
int16_t duid_decoded = 0;
|
int16_t duid_decoded = 0;
|
||||||
|
|
||||||
@@ -369,7 +369,7 @@ void process_ISCH (dsd_opts * opts, dsd_state * state)
|
|||||||
{
|
{
|
||||||
isch_decoded = isch_lookup(isch);
|
isch_decoded = isch_lookup(isch);
|
||||||
|
|
||||||
if (isch_decoded > 0)
|
if (isch_decoded > -1)
|
||||||
{
|
{
|
||||||
int uf_count = isch_decoded & 0x3;
|
int uf_count = isch_decoded & 0x3;
|
||||||
int free = (isch_decoded >> 2) & 0x1;
|
int free = (isch_decoded >> 2) & 0x1;
|
||||||
@@ -411,6 +411,7 @@ void process_ISCH (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isch_decoded = -1; //reset to bad value after running
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,10 +694,20 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|||||||
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
|
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "VCH 0 ");
|
fprintf (stderr, "VCH 0 ");
|
||||||
|
//open MBEout file - slot 1 - USE WITH CAUTION on Phase 2! Consider using a symbol capture bin instead!
|
||||||
|
if (duid_decoded == 0 || duid_decoded == 6) //4V or 2V (voice)
|
||||||
|
{
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) openMbeOutFile (opts, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (state->currentslot == 1 && duid_decoded != 3 && duid_decoded != 12)
|
else if (state->currentslot == 1 && duid_decoded != 3 && duid_decoded != 12)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "VCH 1 ");
|
fprintf (stderr, "VCH 1 ");
|
||||||
|
//open MBEout file - slot 2 - USE WITH CAUTION on Phase 2! Consider using a symbol capture bin instead!
|
||||||
|
if (duid_decoded == 0 || duid_decoded == 6) //4V or 2V (voice)
|
||||||
|
{
|
||||||
|
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_fR == NULL)) openMbeOutFileR (opts, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else fprintf (stderr, "VCH S ");
|
else fprintf (stderr, "VCH S ");
|
||||||
|
|
||||||
@@ -835,6 +846,16 @@ void processP2 (dsd_opts * opts, dsd_state * state)
|
|||||||
//process DUID will run through all collected frames and handle them appropriately
|
//process DUID will run through all collected frames and handle them appropriately
|
||||||
process_P2_DUID (opts, state);
|
process_P2_DUID (opts, state);
|
||||||
state->dmr_stereo = 0;
|
state->dmr_stereo = 0;
|
||||||
state->p2_is_lcch = 0;
|
state->p2_is_lcch = 0;
|
||||||
|
|
||||||
|
//bugfix for OSS dmrbust 16 shim, reset both to 0 upon exit
|
||||||
|
//in case or marginal signal and both get stuck on 16, indefinitely muting the non-preferred slot
|
||||||
|
//but...this can also cause at least one 4v/2v to get through on the other slot if the sync lines up that way
|
||||||
|
if (opts->audio_out_type == 5)
|
||||||
|
{
|
||||||
|
//set both to blank value
|
||||||
|
state->dmrburstL = 17;
|
||||||
|
state->dmrburstR = 17;
|
||||||
|
}
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -915,6 +915,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
fprintf (stderr, "\n RFSS Status Broadcast - Implicit \n");
|
fprintf (stderr, "\n RFSS Status Broadcast - Implicit \n");
|
||||||
fprintf (stderr, " LRA [%02X] SYSID [%03X] RFSS ID [%02X] SITE ID [%02X] CHAN [%04X] SSC [%02X] ", lra, lsysid, rfssid, siteid, channel, sysclass);
|
fprintf (stderr, " LRA [%02X] SYSID [%03X] RFSS ID [%02X] SITE ID [%02X] CHAN [%04X] SSC [%02X] ", lra, lsysid, rfssid, siteid, channel, sysclass);
|
||||||
process_channel_to_freq (opts, state, channel);
|
process_channel_to_freq (opts, state, channel);
|
||||||
|
|
||||||
|
state->p2_siteid = siteid;
|
||||||
|
state->p2_rfssid = rfssid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//RFSS Status Broadcast - Explicit
|
//RFSS Status Broadcast - Explicit
|
||||||
@@ -931,6 +934,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
fprintf (stderr, " LRA [%02X] SYSID [%03X] RFSS ID [%02X] SITE ID [%02X]\n CHAN-T [%04X] CHAN-R [%02X] SSC [%02X] ", lra, lsysid, rfssid, siteid, channelt, channelr, sysclass);
|
fprintf (stderr, " LRA [%02X] SYSID [%03X] RFSS ID [%02X] SITE ID [%02X]\n CHAN-T [%04X] CHAN-R [%02X] SSC [%02X] ", lra, lsysid, rfssid, siteid, channelt, channelr, sysclass);
|
||||||
process_channel_to_freq (opts, state, channelt);
|
process_channel_to_freq (opts, state, channelt);
|
||||||
process_channel_to_freq (opts, state, channelr);
|
process_channel_to_freq (opts, state, channelr);
|
||||||
|
|
||||||
|
state->p2_siteid = siteid;
|
||||||
|
state->p2_rfssid = rfssid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Unit-to-Unit Answer Request (UU_ANS_REQ)
|
//Unit-to-Unit Answer Request (UU_ANS_REQ)
|
||||||
@@ -1079,6 +1085,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
process_channel_to_freq (opts, state, channelr);
|
process_channel_to_freq (opts, state, channelr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->p2_siteid = siteid;
|
||||||
|
state->p2_rfssid = rfssid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Secondary Control Channel Broadcast, Implicit
|
//Secondary Control Channel Broadcast, Implicit
|
||||||
@@ -1108,7 +1117,10 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
state->trunk_lcn_freq[1] = freq1;
|
state->trunk_lcn_freq[1] = freq1;
|
||||||
state->trunk_lcn_freq[2] = freq2;
|
state->trunk_lcn_freq[2] = freq2;
|
||||||
state->lcn_freq_count = 3; //increment to three
|
state->lcn_freq_count = 3; //increment to three
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->p2_siteid = siteid;
|
||||||
|
state->p2_rfssid = rfssid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,6 +202,10 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
|||||||
//print it and then zero out
|
//print it and then zero out
|
||||||
state->lastsrc = 0;
|
state->lastsrc = 0;
|
||||||
state->lasttg = 0;
|
state->lasttg = 0;
|
||||||
|
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (state->currentslot == 0)
|
if (state->currentslot == 0)
|
||||||
{
|
{
|
||||||
@@ -218,6 +222,9 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
|||||||
//print it and then zero out
|
//print it and then zero out
|
||||||
state->lastsrcR = 0;
|
state->lastsrcR = 0;
|
||||||
state->lasttgR = 0;
|
state->lasttgR = 0;
|
||||||
|
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
}
|
}
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
@@ -232,8 +239,9 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
|||||||
}
|
}
|
||||||
if (opcode == 0x4 && err == 0)
|
if (opcode == 0x4 && err == 0)
|
||||||
{
|
{
|
||||||
if (state->currentslot == 1) state->dmrburstL = 21;
|
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
|
||||||
else state->dmrburstR = 21;
|
//if (state->currentslot == 1) state->dmrburstL = 21;
|
||||||
|
//else state->dmrburstR = 21;
|
||||||
fprintf (stderr, " MAC_ACTIVE ");
|
fprintf (stderr, " MAC_ACTIVE ");
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
process_MAC_VPDU(opts, state, 1, SMAC);
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
||||||
@@ -241,8 +249,18 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
|||||||
}
|
}
|
||||||
if (opcode == 0x6 && err == 0)
|
if (opcode == 0x6 && err == 0)
|
||||||
{
|
{
|
||||||
if (state->currentslot == 1) state->dmrburstL = 22;
|
if (state->currentslot == 1)
|
||||||
else state->dmrburstR = 22;
|
{
|
||||||
|
state->dmrburstL = 21;
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->dmrburstR = 21;
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
}
|
||||||
fprintf (stderr, " MAC_HANGTIME ");
|
fprintf (stderr, " MAC_HANGTIME ");
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
process_MAC_VPDU(opts, state, 1, SMAC);
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
||||||
@@ -412,6 +430,10 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
|||||||
//print it and then zero out
|
//print it and then zero out
|
||||||
state->lastsrc = 0;
|
state->lastsrc = 0;
|
||||||
state->lasttg = 0;
|
state->lasttg = 0;
|
||||||
|
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (state->currentslot == 1)
|
if (state->currentslot == 1)
|
||||||
{
|
{
|
||||||
@@ -428,6 +450,9 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
|||||||
//print it and then zero out
|
//print it and then zero out
|
||||||
state->lastsrcR = 0;
|
state->lastsrcR = 0;
|
||||||
state->lasttgR = 0;
|
state->lasttgR = 0;
|
||||||
|
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
}
|
}
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
}
|
}
|
||||||
@@ -462,8 +487,9 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
|||||||
}
|
}
|
||||||
if (opcode == 0x4 && err == 0)
|
if (opcode == 0x4 && err == 0)
|
||||||
{
|
{
|
||||||
if (state->currentslot == 0) state->dmrburstL = 21;
|
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
|
||||||
else state->dmrburstR = 21;
|
//if (state->currentslot == 0) state->dmrburstL = 21;
|
||||||
|
//else state->dmrburstR = 21;
|
||||||
fprintf (stderr, " MAC_ACTIVE ");
|
fprintf (stderr, " MAC_ACTIVE ");
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
process_MAC_VPDU(opts, state, 0, FMAC);
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
||||||
@@ -471,8 +497,18 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
|||||||
}
|
}
|
||||||
if (opcode == 0x6 && err == 0)
|
if (opcode == 0x6 && err == 0)
|
||||||
{
|
{
|
||||||
if (state->currentslot == 0) state->dmrburstL = 22;
|
if (state->currentslot == 0)
|
||||||
else state->dmrburstR = 22;
|
{
|
||||||
|
state->dmrburstL = 22;
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->dmrburstR = 22;
|
||||||
|
//close any open MBEout files
|
||||||
|
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
|
||||||
|
}
|
||||||
fprintf (stderr, " MAC_HANGTIME ");
|
fprintf (stderr, " MAC_HANGTIME ");
|
||||||
fprintf (stderr, "%s", KYEL);
|
fprintf (stderr, "%s", KYEL);
|
||||||
process_MAC_VPDU(opts, state, 0, FMAC);
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ processProVoice (dsd_opts * opts, dsd_state * state)
|
|||||||
#ifdef PROVOICE_DUMP
|
#ifdef PROVOICE_DUMP
|
||||||
fprintf (stderr," ");
|
fprintf (stderr," ");
|
||||||
#endif
|
#endif
|
||||||
//init Bits (64)...MI?
|
//iNitial 64 bits
|
||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
k = 0;
|
k = 0;
|
||||||
//fprintf (stderr, "\nInit 64 ");
|
fprintf (stderr, "\n N64: ");
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
initbyte[i] = 0;
|
initbyte[i] = 0;
|
||||||
@@ -47,9 +47,10 @@ processProVoice (dsd_opts * opts, dsd_state * state)
|
|||||||
initbyte[i] = initbyte[i] | init[k];
|
initbyte[i] = initbyte[i] | init[k];
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "%02X", initbyte[i]);
|
fprintf (stderr, "%02X", initbyte[i]);
|
||||||
|
if (i == 3) fprintf (stderr, "-");
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
// lid
|
// lid
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
@@ -79,7 +80,7 @@ processProVoice (dsd_opts * opts, dsd_state * state)
|
|||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
k = 0;
|
k = 0;
|
||||||
//fprintf (stderr, "LID ");
|
fprintf (stderr, " LID: ");
|
||||||
for(i = 0; i < 10; i++)
|
for(i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
lidbyte[i] = 0;
|
lidbyte[i] = 0;
|
||||||
@@ -89,9 +90,10 @@ processProVoice (dsd_opts * opts, dsd_state * state)
|
|||||||
lidbyte[i] = lidbyte[i] | lid[k];
|
lidbyte[i] = lidbyte[i] | lid[k];
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "%02X", lidbyte[i]);
|
fprintf (stderr, "%02X", lidbyte[i]);
|
||||||
|
if (i == 3 || i == 7) fprintf (stderr, "-");
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "\n");
|
// fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -337,7 +339,7 @@ processProVoice (dsd_opts * opts, dsd_state * state)
|
|||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
k = 0;
|
k = 0;
|
||||||
//fprintf (stderr, "16 bits? ");
|
fprintf (stderr, "\n 16B: ");
|
||||||
for(i = 0; i < 2; i++)
|
for(i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
initbyte[i] = 0;
|
initbyte[i] = 0;
|
||||||
@@ -347,9 +349,9 @@ if (opts->payload == 1)
|
|||||||
initbyte[i] = initbyte[i] | init[k];
|
initbyte[i] = initbyte[i] | init[k];
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "%02X", initbyte[i]);
|
fprintf (stderr, "%02X", initbyte[i]);
|
||||||
}
|
}
|
||||||
//fprintf (stderr, "\n");
|
// fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
// imbe frames 3,4 first half
|
// imbe frames 3,4 first half
|
||||||
w = pW;
|
w = pW;
|
||||||
|
|||||||
Reference in New Issue
Block a user