mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0635ab7121 | ||
|
|
a0d9e349c2 | ||
|
|
7ca65cf687 | ||
|
|
b4a0e2e9f3 | ||
|
|
73f0d5df44 | ||
|
|
b003d0a210 | ||
|
|
83f390ba88 | ||
|
|
c8aafb1be0 |
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
*.[ao]
|
||||||
|
*.so*
|
||||||
|
*.dylib
|
||||||
|
build
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Notice - This branch is now considered 'legacy' and the master branch will be considered the 'main' branch going forward.
|
||||||
|
|
||||||
# Digital Speech Decoder - Florida Man Edition
|
# Digital Speech Decoder - Florida Man Edition
|
||||||
|
|
||||||
This version of DSD is a flavor blend of [szechyjs](https://github.com/szechyjs/dsd "szechyjs") RTL branch and some of my own additions, along with portions of DMR and NXDN code from the [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve") branch. This code also borrows snippets, inspiration, and ideas from other open source works including [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25"), [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"). This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu and hrh17 for the many hours of wav samples submitted by them.
|
This version of DSD is a flavor blend of [szechyjs](https://github.com/szechyjs/dsd "szechyjs") RTL branch and some of my own additions, along with portions of DMR and NXDN code from the [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve") branch. This code also borrows snippets, inspiration, and ideas from other open source works including [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25"), [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"). This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu and hrh17 for the many hours of wav samples submitted by them.
|
||||||
@@ -242,11 +244,6 @@ sudo chmod 777 /usr/share/tone8.wav
|
|||||||
sudo chmod 777 /usr/share/tone24.wav
|
sudo chmod 777 /usr/share/tone24.wav
|
||||||
```
|
```
|
||||||
|
|
||||||
# Join the Conversation
|
|
||||||
|
|
||||||
Want to help drive the direction of this project and read more about the latest updates and releases to DSD-FME? Then join the conversation on the 'unofficial official' [DSD-FME](https://forums.radioreference.com/threads/dsd-fme.438137/ "DSD-FME") Forum Thread on the Radio Reference Forums.
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Copyright (C) 2010 DSD Author
|
Copyright (C) 2010 DSD Author
|
||||||
GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||||
|
|||||||
@@ -873,7 +873,7 @@ void ProcessReservedData(dsd_opts * opts, dsd_state * state, uint8_t info[196],
|
|||||||
void ProcessUnifiedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
void ProcessUnifiedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||||
|
|
||||||
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
||||||
int LFSR(dsd_state * state);
|
void LFSR(dsd_state * state);
|
||||||
void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state);
|
void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state);
|
||||||
|
|
||||||
void Hamming_7_4_init();
|
void Hamming_7_4_init();
|
||||||
|
|||||||
@@ -1757,32 +1757,6 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t
|
|||||||
sprintf(state->dmr_branding, " Hytera XPT ");
|
sprintf(state->dmr_branding, " Hytera XPT ");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Testing CSBK Voice Call on Tait //CSBK Protect RID ILLEGALLY_PARKED
|
|
||||||
// if ((IrrecoverableErrors == 0) && CRCCorrect)
|
|
||||||
// {
|
|
||||||
// if (DmrDataByte[0] == 0xAF)
|
|
||||||
// {
|
|
||||||
// if (state->currentslot == 0)
|
|
||||||
// {
|
|
||||||
// state->lastsrc = (DmrDataByte[4] << 16) | (DmrDataByte[5] << 8) | (DmrDataByte[6] << 0);
|
|
||||||
// state->lasttg = (DmrDataByte[7] << 16) | (DmrDataByte[8] << 8) | (DmrDataByte[9] << 0);
|
|
||||||
// fprintf (stderr, "%s", KGRN);
|
|
||||||
// fprintf (stderr, "\n SLOT %d ", state->currentslot+1);
|
|
||||||
// fprintf(stderr, "TGT=%u SRC=%u ", state->lasttg, state->lastsrc);
|
|
||||||
// fprintf(stderr, " CSBK Voice LC??");
|
|
||||||
// }
|
|
||||||
// if (state->currentslot == 1)
|
|
||||||
// {
|
|
||||||
// state->lastsrcR = (DmrDataByte[4] << 16) | (DmrDataByte[5] << 8) | (DmrDataByte[6] << 0);
|
|
||||||
// state->lasttgR = (DmrDataByte[7] << 16) | (DmrDataByte[8] << 8) | (DmrDataByte[9] << 0);
|
|
||||||
// fprintf (stderr, "%s", KGRN);
|
|
||||||
// fprintf (stderr, "\n SLOT %d ", state->currentslot+1);
|
|
||||||
// fprintf(stderr, "TGT=%u SRC=%u ", state->lasttgR, state->lastsrcR);
|
|
||||||
// fprintf(stderr, " CSBK Voice LC??");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Full
|
//Full
|
||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
@@ -2049,9 +2023,12 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19
|
|||||||
|
|
||||||
/* Store the Source address */
|
/* Store the Source address */
|
||||||
TSVoiceSupFrame->FullLC.SourceAddress = (unsigned int)ConvertBitIntoBytes(&DmrDataBit[48], 24);
|
TSVoiceSupFrame->FullLC.SourceAddress = (unsigned int)ConvertBitIntoBytes(&DmrDataBit[48], 24);
|
||||||
//truncate if Byte 0 isn't 0, 0x04 (or other) may signify a Cap+ System
|
|
||||||
if (DmrDataByte != 0x0)
|
int rest_channel = -1; //set rest_channel to -1; if set to other value, then we know we have a Cap+?
|
||||||
|
//Below "Should" be a MotoTRBO Cap+ system
|
||||||
|
if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode & 0x4 && TSVoiceSupFrame->FullLC.FeatureSetID == 0x10)
|
||||||
{
|
{
|
||||||
|
rest_channel = (TSVoiceSupFrame->FullLC.SourceAddress >> 16); //8 bits for Rest Channel
|
||||||
TSVoiceSupFrame->FullLC.SourceAddress = TSVoiceSupFrame->FullLC.SourceAddress & 0xFFFF;
|
TSVoiceSupFrame->FullLC.SourceAddress = TSVoiceSupFrame->FullLC.SourceAddress & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2144,37 +2121,12 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19
|
|||||||
else if(IrrecoverableErrors == 0) {}//fprintf(stderr, "RAS (FEC OK/CRC ERR)");
|
else if(IrrecoverableErrors == 0) {}//fprintf(stderr, "RAS (FEC OK/CRC ERR)");
|
||||||
else {}//fprintf(stderr, "(FEC FAIL/CRC ERR)");
|
else {}//fprintf(stderr, "(FEC FAIL/CRC ERR)");
|
||||||
|
|
||||||
#ifdef PRINT_VOICE_LC_HEADER_BYTES
|
//check Cap+ rest channel info if available
|
||||||
fprintf(stderr, "\n");
|
if (rest_channel != -1)
|
||||||
fprintf(stderr, "VOICE LC HEADER : ");
|
|
||||||
for(i = 0; i < 12; i++)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "0x%02X", DmrDataByte[i]);
|
//fprintf (stderr, "Cap+ R-Ch=%d", rest_channel);
|
||||||
if(i != 11) fprintf(stderr, " - ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
fprintf(stderr, "BPTC(196,96) Reserved bit R(0)-R(2) = 0x%02X\n", BPTCReservedBits);
|
|
||||||
|
|
||||||
fprintf(stderr, "CRC extracted = 0x%04X - CRC computed = 0x%04X - ", CRCExtracted, CRCComputed);
|
|
||||||
|
|
||||||
if((IrrecoverableErrors == 0) && CRCCorrect)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "CRCs are equal + FEC OK !\n");
|
|
||||||
}
|
|
||||||
else if(IrrecoverableErrors == 0)
|
|
||||||
{
|
|
||||||
else fprintf(stderr, "FEC correctly corrected but CRCs are incorrect\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "ERROR !!! CRCs are different and FEC Failed !\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Hamming Irrecoverable Errors = %u\n", IrrecoverableErrors);
|
|
||||||
#endif /* PRINT_VOICE_LC_HEADER_BYTES */
|
|
||||||
|
|
||||||
//Full
|
//Full
|
||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
@@ -2747,7 +2699,7 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state)
|
|||||||
} /* End ProcessVoiceBurstSync() */
|
} /* End ProcessVoiceBurstSync() */
|
||||||
|
|
||||||
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
//LFSR code courtesy of https://github.com/mattames/LFSR/
|
||||||
int LFSR(dsd_state * state)
|
void LFSR(dsd_state * state)
|
||||||
{
|
{
|
||||||
|
|
||||||
int lfsr = 0;
|
int lfsr = 0;
|
||||||
|
|||||||
@@ -1156,7 +1156,7 @@ main (int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T': //repurposed to TDMA/NXDN Per Call
|
case 'T': //repurposed to TDMA/NXDN Per Call
|
||||||
sprintf (wav_file_directory, "./WAV"); // /wav, or ./wav
|
sprintf (wav_file_directory, "./WAV");
|
||||||
wav_file_directory[1023] = '\0';
|
wav_file_directory[1023] = '\0';
|
||||||
if (stat(wav_file_directory, &st) == -1)
|
if (stat(wav_file_directory, &st) == -1)
|
||||||
{
|
{
|
||||||
@@ -1165,17 +1165,19 @@ main (int argc, char **argv)
|
|||||||
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
|
||||||
}
|
}
|
||||||
fprintf (stderr,"XDMA and NXDN Per Call Wav File Saving Enabled. (NCurses Terminal Only)\n");
|
fprintf (stderr,"XDMA and NXDN Per Call Wav File Saving Enabled. (NCurses Terminal Only)\n");
|
||||||
sprintf (opts.wav_out_file, "./WAV/DSD-FME-X1.wav"); // foward slash here, on wav_file_directory?
|
sprintf (opts.wav_out_file, "./WAV/DSD-FME-X1.wav");
|
||||||
sprintf (opts.wav_out_fileR, "./WAV/DSD-FME-X2.wav");
|
sprintf (opts.wav_out_fileR, "./WAV/DSD-FME-X2.wav");
|
||||||
opts.dmr_stereo_wav = 1;
|
opts.dmr_stereo_wav = 1;
|
||||||
openWavOutFileL (&opts, &state); //testing for now, will want to move to per call later
|
openWavOutFileL (&opts, &state);
|
||||||
openWavOutFileR (&opts, &state); //testing for now, will want to move to per call later
|
openWavOutFileR (&opts, &state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
opts.aggressive_framesync = 0;
|
opts.aggressive_framesync = 0;
|
||||||
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 DMR CACH/Burst FEC Pass/Fail\n");
|
||||||
fprintf (stderr, "%s", KNRM);
|
fprintf (stderr, "%s", KNRM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -143,9 +143,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
// 0 +P25p1
|
// 0 +P25p1
|
||||||
// 1 -P25p1
|
// 1 -P25p1
|
||||||
state->errs = mbe_eccImbe7200x4400C0 (imbe_fr);
|
state->errs = mbe_eccImbe7200x4400C0 (imbe_fr);
|
||||||
state->errs2 = state->errs;
|
//state->errs2 = state->errs;
|
||||||
mbe_demodulateImbe7200x4400Data (imbe_fr);
|
mbe_demodulateImbe7200x4400Data (imbe_fr);
|
||||||
state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
|
state->errs2 = mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -170,9 +170,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
{
|
{
|
||||||
|
|
||||||
state->errs = mbe_eccImbe7100x4400C0 (imbe7100_fr);
|
state->errs = mbe_eccImbe7100x4400C0 (imbe7100_fr);
|
||||||
state->errs2 = state->errs;
|
//state->errs2 = state->errs;
|
||||||
mbe_demodulateImbe7100x4400Data (imbe7100_fr);
|
mbe_demodulateImbe7100x4400Data (imbe7100_fr);
|
||||||
state->errs2 += mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d);
|
state->errs2 = mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d);
|
||||||
mbe_convertImbe7100to7200(imbe_d); //needs extra conversion step apparently
|
mbe_convertImbe7100to7200(imbe_d); //needs extra conversion step apparently
|
||||||
|
|
||||||
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||||
@@ -203,10 +203,11 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
}
|
}
|
||||||
else if ((state->synctype == 8) || (state->synctype == 9))
|
else if ((state->synctype == 8) || (state->synctype == 9))
|
||||||
{
|
{
|
||||||
|
|
||||||
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
||||||
state->errs2 = state->errs;
|
//state->errs2 = state->errs;
|
||||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
state->errs2 = mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||||
|
|
||||||
if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) ||
|
if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) ||
|
||||||
(state->M == 1 && state->R > 0) )
|
(state->M == 1 && state->R > 0) )
|
||||||
@@ -248,9 +249,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
{
|
{
|
||||||
|
|
||||||
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
||||||
state->errs2 = state->errs;
|
//state->errs2 = state->errs;
|
||||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
state->errs2 = mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||||
|
|
||||||
if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) ||
|
if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) ||
|
||||||
(state->K > 0 && state->M == 1) )
|
(state->K > 0 && state->M == 1) )
|
||||||
@@ -343,9 +344,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
{
|
{
|
||||||
|
|
||||||
state->errsR = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
state->errsR = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
||||||
state->errs2R = state->errsR;
|
//state->errs2R = state->errsR;
|
||||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||||
state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
state->errs2R = mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||||
|
|
||||||
if ( (state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x10) ||
|
if ( (state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x10) ||
|
||||||
(state->K > 0 && state->M == 1) )
|
(state->K > 0 && state->M == 1) )
|
||||||
@@ -433,7 +434,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
//X2-TDMA? Not sure what still makes it this far to run under Framef
|
||||||
if (opts->dmr_stereo == 0)
|
if (opts->dmr_stereo == 0)
|
||||||
{
|
{
|
||||||
mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ int i = 0;
|
|||||||
char versionstr[25];
|
char versionstr[25];
|
||||||
unsigned long long int call_matrix[33][6];
|
unsigned long long int call_matrix[33][6];
|
||||||
|
|
||||||
|
|
||||||
char * FM_bannerN[9] = {
|
char * FM_bannerN[9] = {
|
||||||
" ESC or Arrow Keys For Menu ",
|
" ESC or Arrow Keys For Menu ",
|
||||||
" ██████╗ ██████╗██████╗ ███████╗███╗ ███╗███████╗ ",
|
" ██████╗ ██████╗██████╗ ███████╗███╗ ███╗███████╗ ",
|
||||||
@@ -77,6 +78,8 @@ char * FM_bannerN[9] = {
|
|||||||
" "
|
" "
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char * SyncTypes[44] = {
|
char * SyncTypes[44] = {
|
||||||
"P25P1",
|
"P25P1",
|
||||||
"P25P1",
|
"P25P1",
|
||||||
@@ -88,10 +91,10 @@ char * SyncTypes[44] = {
|
|||||||
"DSTAR",
|
"DSTAR",
|
||||||
"NXDN VOICE",
|
"NXDN VOICE",
|
||||||
"NXDN VOICE",
|
"NXDN VOICE",
|
||||||
"DMR DATA", //10
|
"DMR ", //10
|
||||||
"DMR DATA",
|
"DMR ",
|
||||||
"DMR VOICE",
|
"DMR ",
|
||||||
"DMR VOICE",
|
"DMR ",
|
||||||
"PROVOICE",
|
"PROVOICE",
|
||||||
"PROVOICE",
|
"PROVOICE",
|
||||||
"NXDN VOICE", //DATA
|
"NXDN VOICE", //DATA
|
||||||
@@ -123,7 +126,7 @@ char * SyncTypes[44] = {
|
|||||||
|
|
||||||
char * DMRBusrtTypes[32] = {
|
char * DMRBusrtTypes[32] = {
|
||||||
"PI Header ",
|
"PI Header ",
|
||||||
"VOICE LC HDR ",
|
"VOICE LC ",
|
||||||
"TLC ",
|
"TLC ",
|
||||||
"CSBK ",
|
"CSBK ",
|
||||||
"MBC Header ",
|
"MBC Header ",
|
||||||
@@ -132,7 +135,7 @@ char * DMRBusrtTypes[32] = {
|
|||||||
"RATE 1/2 DATA ",
|
"RATE 1/2 DATA ",
|
||||||
"RATE 3/4 DATA ",
|
"RATE 3/4 DATA ",
|
||||||
"Slot Idle ",
|
"Slot Idle ",
|
||||||
"Rate 1 DATA ",
|
"RATE 1 DATA ",
|
||||||
"ERR ", //These values for ERR may be Reserved for use in future?
|
"ERR ", //These values for ERR may be Reserved for use in future?
|
||||||
"DUID ERR ",
|
"DUID ERR ",
|
||||||
"R-S ERR ",
|
"R-S ERR ",
|
||||||
@@ -152,11 +155,16 @@ char * DMRBusrtTypes[32] = {
|
|||||||
"VOICE LDU",
|
"VOICE LDU",
|
||||||
"TDU/TDULC",
|
"TDU/TDULC",
|
||||||
"TSBK",
|
"TSBK",
|
||||||
"MAC_SIGNAL",
|
"MAC SIGNAL",
|
||||||
"MAC_SIGNAL"
|
"MAC SIGNAL"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//there is still a bug in beeper, but the bug isn't related to call history,
|
||||||
|
//if it were, per call wav would also be affected.
|
||||||
|
//seems to do with playing a wav file,
|
||||||
|
//debug shows it should trigger even when you don't hear it
|
||||||
|
//no beep or double beep still happens randomly but debug shows only one played!?
|
||||||
void beeper (dsd_opts * opts, dsd_state * state, int type)
|
void beeper (dsd_opts * opts, dsd_state * state, int type)
|
||||||
{
|
{
|
||||||
FILE *beep;
|
FILE *beep;
|
||||||
@@ -176,7 +184,8 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
|
|||||||
if (stat(wav_name, &stat_buf) == 0)
|
if (stat(wav_name, &stat_buf) == 0)
|
||||||
{
|
{
|
||||||
beep = fopen (wav_name, "ro");
|
beep = fopen (wav_name, "ro");
|
||||||
uint8_t buf[1024] = {0};
|
uint8_t buf[1024];
|
||||||
|
memset (buf, 0, sizeof(buf));
|
||||||
short blip = 0;
|
short blip = 0;
|
||||||
int loop = 1;
|
int loop = 1;
|
||||||
while (loop == 1)
|
while (loop == 1)
|
||||||
@@ -192,14 +201,17 @@ void beeper (dsd_opts * opts, dsd_state * state, int type)
|
|||||||
if (type == 0 && opts->dmr_stereo == 1 && opts->audio_out == 1)
|
if (type == 0 && opts->dmr_stereo == 1 && opts->audio_out == 1)
|
||||||
{
|
{
|
||||||
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
|
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
|
||||||
|
//fprintf (stderr, "BEEP 0 24\n");
|
||||||
}
|
}
|
||||||
if (type == 1 && opts->dmr_stereo == 1 && opts->audio_out == 1)
|
if (type == 1 && opts->dmr_stereo == 1 && opts->audio_out == 1)
|
||||||
{
|
{
|
||||||
pa_simple_write(opts->pulse_digi_dev_outR, buf, sizeof(buf), NULL);
|
pa_simple_write(opts->pulse_digi_dev_outR, buf, sizeof(buf), NULL);
|
||||||
|
//fprintf (stderr, "BEEP 1 24\n");
|
||||||
}
|
}
|
||||||
if (opts->dmr_stereo == 0 && opts->audio_out == 1)
|
if (opts->dmr_stereo == 0 && opts->audio_out == 1)
|
||||||
{
|
{
|
||||||
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
|
pa_simple_write(opts->pulse_digi_dev_out, buf, sizeof(buf), NULL);
|
||||||
|
//fprintf (stderr, "BEEP 0 8\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -240,6 +252,30 @@ char * getTimeN(void) //get pretty hh:mm:ss timestamp
|
|||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * getDateC(time_t t) {
|
||||||
|
char datename[99]; //Ubuntu 32-bit, use 80; everything else, use 99
|
||||||
|
char * curr2;
|
||||||
|
struct tm * to;
|
||||||
|
|
||||||
|
to = localtime( & t);
|
||||||
|
strftime(datename, sizeof(datename), "%Y-%m-%d", to);
|
||||||
|
curr2 = strtok(datename, " ");
|
||||||
|
return curr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * getTimeC(time_t t) //get pretty hh:mm:ss timestamp
|
||||||
|
{
|
||||||
|
char * curr;
|
||||||
|
char * stamp = asctime(localtime( & t));
|
||||||
|
|
||||||
|
curr = strtok(stamp, " ");
|
||||||
|
curr = strtok(NULL, " ");
|
||||||
|
curr = strtok(NULL, " ");
|
||||||
|
curr = strtok(NULL, " ");
|
||||||
|
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
//testing a few things, going to put this into ncursesMenu
|
//testing a few things, going to put this into ncursesMenu
|
||||||
#define WIDTH 36
|
#define WIDTH 36
|
||||||
#define HEIGHT 23
|
#define HEIGHT 23
|
||||||
@@ -1614,15 +1650,17 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//DMR SRC
|
//DMR SRC
|
||||||
// if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) )
|
if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) )
|
||||||
if ( (lls == 12 || lls == 11 || lls == 32) )
|
//if ( (lls == 12 || lls == 11 || lls == 32) )
|
||||||
{
|
{
|
||||||
if (state->dmrburstL == 16 && state->lastsrc > 0) //state->currentslot == 0 &&
|
//if (state->dmrburstL == 16 && state->lastsrc > 0) //state->currentslot == 0 &&
|
||||||
|
if (state->lastsrc > 0)
|
||||||
{
|
{
|
||||||
rd = state->lastsrc;
|
rd = state->lastsrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->dmrburstR == 16 && state->lastsrcR > 0) //state->currentslot == 1 &&
|
//if (state->dmrburstR == 16 && state->lastsrcR > 0) //state->currentslot == 1 &&
|
||||||
|
if (state->lastsrcR > 0)
|
||||||
{
|
{
|
||||||
rdR = state->lastsrcR;
|
rdR = state->lastsrcR;
|
||||||
}
|
}
|
||||||
@@ -1630,14 +1668,17 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//DMR TG
|
//DMR TG
|
||||||
if ( (lls == 12 || lls == 11 || lls == 32) )
|
if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) )
|
||||||
|
//if ( (lls == 12 || lls == 11 || lls == 32) )
|
||||||
{
|
{
|
||||||
if (state->dmrburstL == 16 && state->lasttg > 0) //state->currentslot == 0 &&
|
//if (state->dmrburstL == 16 && state->lasttg > 0) //state->currentslot == 0 &&
|
||||||
|
if (state->lasttg > 0)
|
||||||
{
|
{
|
||||||
tg = state->lasttg;
|
tg = state->lasttg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->dmrburstR == 16 && state->lasttgR > 0) //state->currentslot == 1 &&
|
//if (state->dmrburstR == 16 && state->lasttgR > 0) //state->currentslot == 1 &&
|
||||||
|
if (state->lasttgR > 0)
|
||||||
{
|
{
|
||||||
tgR = state->lasttgR;
|
tgR = state->lasttgR;
|
||||||
|
|
||||||
@@ -1785,13 +1826,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1)
|
||||||
{
|
{
|
||||||
|
//fprintf (stderr, "BEEP 0 MS LEFT\n");
|
||||||
beeper (opts, state, 0);
|
beeper (opts, state, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//DMR BS Slot 1 - matrix 0-4
|
//DMR BS Slot 1 - matrix 0-4
|
||||||
if ( call_matrix[4][2] != rd && (lls == 11 || lls == 12 || lls == 35 || lls == 36) )
|
if ( call_matrix[4][2] != rd && (lls == 11 || lls == 12 || lls == 10 || lls == 13 || lls == 35 || lls == 36) )
|
||||||
{
|
{
|
||||||
|
|
||||||
for (short int k = 0; k < 4; k++)
|
for (short int k = 0; k < 4; k++)
|
||||||
@@ -1823,13 +1865,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1)
|
||||||
{
|
{
|
||||||
|
//fprintf (stderr, "BEEP 0 BS LEFT\n");
|
||||||
beeper (opts, state, 0);
|
beeper (opts, state, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//DMR BS Slot 2 - matrix 5-9
|
//DMR BS Slot 2 - matrix 5-9
|
||||||
if ( call_matrix[9][2] != rdR && (lls == 11 || lls == 12 || lls == 35 || lls == 36) )
|
if ( call_matrix[9][2] != rdR && (lls == 11 || lls == 12 || lls == 10 || lls == 13 || lls == 35 || lls == 36) )
|
||||||
{
|
{
|
||||||
|
|
||||||
for (short int k = 5; k < 9; k++)
|
for (short int k = 5; k < 9; k++)
|
||||||
@@ -1860,6 +1903,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
if (opts->call_alert == 1)
|
if (opts->call_alert == 1)
|
||||||
{
|
{
|
||||||
|
//fprintf (stderr, "BEEP 1 BS RIGHT\n");
|
||||||
beeper (opts, state, 1);
|
beeper (opts, state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2553,7 +2597,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||||||
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
||||||
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
|
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
|
||||||
}
|
}
|
||||||
printw ("%lld secs ago\n", time(NULL) - call_matrix[9-j][5]);
|
|
||||||
|
printw ("%s ", getDateC(call_matrix[9-j][5]) ); //You're welcome
|
||||||
|
printw ("%s \n", getTimeC(call_matrix[9-j][5]) ); //Roman
|
||||||
}
|
}
|
||||||
} //end Call History
|
} //end Call History
|
||||||
//fence bottom
|
//fence bottom
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
/*-------------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------------
|
||||||
* p25p1_tsbk.c
|
* p25p1_tsbk.c
|
||||||
* P25 Trunking Signal Block Handler
|
* P25p1 Trunking Signal Block Handler
|
||||||
*
|
*
|
||||||
* LWVMOBILE
|
* LWVMOBILE
|
||||||
* 2022-09 DSD-FME Florida Man Edition
|
* 2022-10 DSD-FME Florida Man Edition
|
||||||
*-----------------------------------------------------------------------------*/
|
*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "dsd.h"
|
#include "dsd.h"
|
||||||
void processTSBK(dsd_opts * opts, dsd_state * state)
|
void processTSBK(dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
//process TSDU/TSBK and look for relevant data (WACN, SYSID, iden_up, other goodies later on)
|
|
||||||
int tsbkbit[196] = {0}; //tsbk bit array, 196 trellis encoded bits
|
int tsbkbit[196] = {0}; //tsbk bit array, 196 trellis encoded bits
|
||||||
int tsbk_dibit[98] = {0};
|
int tsbk_dibit[98] = {0};
|
||||||
|
|
||||||
int dibit = 0;
|
int dibit = 0;
|
||||||
uint8_t tsbk_byte[12] = {0}; //12 byte return from bd_bridge (block_deinterleave)
|
uint8_t tsbk_byte[12] = {0}; //12 byte return from bd_bridge (block_deinterleave)
|
||||||
unsigned long long int PDU[24] = {0}; //24 byte PDU to send to the tsbk_byte vPDU handler, should be same formats
|
unsigned long long int PDU[24] = {0}; //24 byte PDU to send to the tsbk_byte vPDU handler, should be same formats (mostly)
|
||||||
int tsbk_decoded_bits[190] = {0}; //decoded bits from tsbk_bytes for sending to crc16_lb_bridge
|
int tsbk_decoded_bits[190] = {0}; //decoded bits from tsbk_bytes for sending to crc16_lb_bridge
|
||||||
int i, j, k, b, x, y;
|
int i, j, k, b, x, y;
|
||||||
int ec = -2; //error value returned from (block_deinterleave)
|
int ec = -2; //error value returned from (block_deinterleave)
|
||||||
int checksum = -2; //checksum returned from crc16, 0 is valid, anything else is invalid
|
int err = -2; //error value returned from crc16_lb_bridge
|
||||||
int skipdibit = 14; //initial status dibit will occur at 14, then add 35 each time it occurs
|
int skipdibit = 14; //initial status dibit will occur at 14, then add 36 each time it occurs
|
||||||
|
int protectbit = 0;
|
||||||
|
int MFID = 0xFF; //Manufacturer ID - Might be beneficial to NOT send anything but standard 0x00 or 0x01 messages
|
||||||
|
|
||||||
|
//Update: Identified Bug in skipdibit incrememnt causing many block deinterleave/crc failures
|
||||||
|
//with correct values set, now we are decoding many more TSBKs
|
||||||
|
//TODO: Don't Print TSBKs/vPDUs unless verbosity levels set higher
|
||||||
//TSBKs are always single block, but up to three can be transmitted in a row,
|
//TSBKs are always single block, but up to three can be transmitted in a row,
|
||||||
//my observation shows that, as far as I know, only the first block of three is good,
|
//Multi-Block PDUs are sent on a different DUID - 0xC (not handled currently)
|
||||||
//and NULL types can contain some amount of garbage, but the CRC is always 00s.
|
|
||||||
//Multi-Block PDUs are sent on a different DUID - 0xC
|
|
||||||
//Best way to proceed for now is going to be to collect all three potentials, and only process on good
|
|
||||||
//de-interleaves AND good CRCs, otherwise, ignore them
|
|
||||||
//The Last Block flag doesn't really seem to apply for some reason (byte 0 0x80), or is always on a garbage block
|
|
||||||
|
|
||||||
//collect three reps of 101 dibits (98 valid dibits with status dibits interlaced)
|
//collect three reps of 101 dibits (98 valid dibits with status dibits interlaced)
|
||||||
for (j = 0; j < 3; j++)
|
for (j = 0; j < 3; j++)
|
||||||
@@ -49,7 +49,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
if (i+(j*101) == skipdibit)
|
if (i+(j*101) == skipdibit)
|
||||||
{
|
{
|
||||||
skipdibit += 35;
|
skipdibit += 36; //was set to 35, this was the bug
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -68,16 +68,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = -2;
|
|
||||||
err = crc16_lb_bridge(tsbk_decoded_bits, 80);
|
err = crc16_lb_bridge(tsbk_decoded_bits, 80);
|
||||||
if (ec != 0)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "BAD BLOCK DEINTERLEAVE");
|
|
||||||
}
|
|
||||||
if (err != 0)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "BAD CRC16");
|
|
||||||
}
|
|
||||||
|
|
||||||
//shuffle corrected bits back into tsbk_byte
|
//shuffle corrected bits back into tsbk_byte
|
||||||
k = 0;
|
k = 0;
|
||||||
@@ -93,9 +84,11 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
tsbk_byte[i] = byte;
|
tsbk_byte[i] = byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
//convert tsbk_byte to PDU and send to vPDU handler...may or may not be entirely compatible,
|
//convert tsbk_byte to PDU and send to vPDU handler
|
||||||
|
//...may or may not be entirely compatible,
|
||||||
|
MFID = tsbk_byte[1];
|
||||||
PDU[0] = 0x07; //P25p1 TSBK Duid 0x07
|
PDU[0] = 0x07; //P25p1 TSBK Duid 0x07
|
||||||
PDU[1] = tsbk_byte[0];
|
PDU[1] = tsbk_byte[0] & 0x3F;
|
||||||
PDU[2] = tsbk_byte[2];
|
PDU[2] = tsbk_byte[2];
|
||||||
PDU[3] = tsbk_byte[3];
|
PDU[3] = tsbk_byte[3];
|
||||||
PDU[4] = tsbk_byte[4];
|
PDU[4] = tsbk_byte[4];
|
||||||
@@ -109,8 +102,12 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
PDU[11] = 0; //tsbk_byte[11];
|
PDU[11] = 0; //tsbk_byte[11];
|
||||||
PDU[1] = PDU[1] ^ 0x40; //flip bit to make it compatible with MAC_PDUs, i.e. 3D to 7D
|
PDU[1] = PDU[1] ^ 0x40; //flip bit to make it compatible with MAC_PDUs, i.e. 3D to 7D
|
||||||
|
|
||||||
//Don't run NET_STS out of this, or will set wrong NAC/CC
|
//check the protect bit, don't run if protected
|
||||||
if (err == 0 && ec == 0 && PDU[1] != 0x7B && PDU[1] != 0xFB && PDU[1] != 0x49 && PDU[1] != 0x45) //0x49 is telephone grant, 0x46 Unit to Unit Channel Answer Request
|
protectbit = (tsbk_byte[0] >> 6) & 0x1;
|
||||||
|
|
||||||
|
//Don't run NET_STS out of this, or will set wrong NAC/CC //&& PDU[1] != 0x49 && PDU[1] != 0x45
|
||||||
|
//0x49 is telephone grant, 0x46 Unit to Unit Channel Answer Request (seems bogus)
|
||||||
|
if (MFID < 0x2 && protectbit == 0 && err == 0 && ec == 0 && PDU[1] != 0x7B )
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s",KMAG);
|
fprintf (stderr, "%s",KMAG);
|
||||||
process_MAC_VPDU(opts, state, 0, PDU);
|
process_MAC_VPDU(opts, state, 0, PDU);
|
||||||
@@ -118,20 +115,23 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//set our WACN and SYSID here now that we have valid ec and crc/checksum
|
//set our WACN and SYSID here now that we have valid ec and crc/checksum
|
||||||
if (err == 0 && ec == 0 && tsbk_byte[0] == 0x3B)
|
if (protectbit == 0 && err == 0 && ec == 0 && (tsbk_byte[0] & 0x3F) == 0x3B)
|
||||||
{
|
{
|
||||||
//only set IF these values aren't already hard set by the user
|
long int wacn = (tsbk_byte[3] << 12) | (tsbk_byte[4] << 4) | (tsbk_byte[5] >> 4);;
|
||||||
if (state->p2_hardset == 0)
|
int sysid = ((tsbk_byte[5] & 0xF) << 8) | tsbk_byte[6];
|
||||||
{
|
|
||||||
state->p2_wacn = (tsbk_byte[3] << 12) | (tsbk_byte[4] << 4) | (tsbk_byte[5] >> 4);
|
|
||||||
state->p2_sysid = ((tsbk_byte[5] & 0xF) << 8) | tsbk_byte[6];
|
|
||||||
int channel = (tsbk_byte[7] << 8) | tsbk_byte[8];
|
int channel = (tsbk_byte[7] << 8) | tsbk_byte[8];
|
||||||
fprintf (stderr, "%s",KMAG);
|
fprintf (stderr, "%s",KMAG);
|
||||||
fprintf (stderr, "\n Network Status Broadcast TSBK - Abbreviated \n");
|
fprintf (stderr, "\n Network Status Broadcast TSBK - Abbreviated \n");
|
||||||
fprintf (stderr, " WACN [%05llX] SYSID [%03llX] NAC [%03llX]", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
fprintf (stderr, " WACN [%05lX] SYSID [%03X] NAC [%03llX]", wacn, sysid, state->p2_cc);
|
||||||
|
|
||||||
state->p25_cc_freq = process_channel_to_freq(opts, state, channel);
|
state->p25_cc_freq = process_channel_to_freq(opts, state, channel);
|
||||||
|
|
||||||
|
//only set IF these values aren't already hard set by the user
|
||||||
|
if (state->p2_hardset == 0)
|
||||||
|
{
|
||||||
|
state->p2_wacn = wacn;
|
||||||
|
state->p2_sysid = sysid;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->payload == 1)
|
if (opts->payload == 1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s",KCYN);
|
fprintf (stderr, "%s",KCYN);
|
||||||
@@ -145,11 +145,17 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//reset for next rep
|
//reset for next rep
|
||||||
ec = -2;
|
ec = -2;
|
||||||
checksum = -2;
|
err = -2;
|
||||||
|
protectbit = 0;
|
||||||
|
MFID = 0xFF;
|
||||||
|
|
||||||
|
//check for last block bit
|
||||||
|
if ( (tsbk_byte[0] >> 7) == 1 )
|
||||||
|
{
|
||||||
|
j = 4; //set j to break the loop early
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*-------------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------------
|
||||||
* p25_p2.c
|
* p25p2_frame.c
|
||||||
* Phase 2 TDMA Voice Processing
|
* Phase 2 TDMA Frame Processing
|
||||||
*
|
*
|
||||||
* original copyrights for portions used below (OP25 DUID table, MAC len table)
|
* original copyrights for portions used below (OP25 DUID table, MAC len table)
|
||||||
*
|
*
|
||||||
@@ -31,9 +31,9 @@ static const int16_t duid_lookup[256] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//4V and 2V deinterleave schedule
|
//4V and 2V deinterleave schedule
|
||||||
const int c0[24] = {
|
const int c0[25] = {
|
||||||
23,5,22,4,21,3,20,2,19,1,18,0,
|
23,5,22,4,21,3,20,2,19,1,18,0,
|
||||||
17,16,15,14,13,12,11,10,9,7,6
|
17,16,15,14,13,12,11,10,9,8,7,6
|
||||||
};
|
};
|
||||||
|
|
||||||
const int c1[24] = {
|
const int c1[24] = {
|
||||||
@@ -41,20 +41,20 @@ const int c1[24] = {
|
|||||||
19,1,18,0,17,16,15,14,13,12,11
|
19,1,18,0,17,16,15,14,13,12,11
|
||||||
};
|
};
|
||||||
|
|
||||||
const int c2[24] = {
|
const int c2[12] = {
|
||||||
3,2,1,0,10,9,8,7,6,5,4
|
3,2,1,0,10,9,8,7,6,5,4
|
||||||
};
|
};
|
||||||
|
|
||||||
const int c3[24] = {
|
const int c3[15] = {
|
||||||
13,12,11,10,9,8,7,6,5,4,3,2,1,0
|
13,12,11,10,9,8,7,6,5,4,3,2,1,0
|
||||||
};
|
};
|
||||||
|
|
||||||
const int csubset[72] = {
|
const int csubset[73] = {
|
||||||
0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,
|
0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,
|
||||||
0,0,1,3,0,0,1,3,0,1,1,3,0,1,1,3,
|
0,0,1,3,0,0,1,3,0,1,1,3,0,1,1,3,
|
||||||
0,1,1,3,0,1,1,3,0,1,1,3,0,1,2,3,
|
0,1,1,3,0,1,1,3,0,1,1,3,0,1,2,3,
|
||||||
0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,
|
0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,
|
||||||
0,1,2,3
|
0,1,2,3,0,1,2,3
|
||||||
};
|
};
|
||||||
|
|
||||||
const int *w;
|
const int *w;
|
||||||
@@ -92,8 +92,9 @@ int sacch_rs[2][132] = {0};
|
|||||||
//store an entire p2 superframe worth of dibits into a bit buffer
|
//store an entire p2 superframe worth of dibits into a bit buffer
|
||||||
void p2_dibit_buffer (dsd_opts * opts, dsd_state * state)
|
void p2_dibit_buffer (dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
|
//we used to grab 2140 (entire superframe minus sync)
|
||||||
for (int i = 0; i < 2140; i++) //2160 for an entire superframe of dibits - 20 sync dibits
|
//now we grab 700 (4 Timeslots minus sync)
|
||||||
|
for (int i = 0; i < 700; i++) //2160 for an entire superframe of dibits - 20 sync dibits
|
||||||
{
|
{
|
||||||
//symbol capture reading now handled directly by getSymbol and getDibit
|
//symbol capture reading now handled directly by getSymbol and getDibit
|
||||||
dibit = getDibit(opts, state);
|
dibit = getDibit(opts, state);
|
||||||
@@ -103,16 +104,7 @@ void p2_dibit_buffer (dsd_opts * opts, dsd_state * state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//grab the entire VCH S-ISCH from the buffer and tack it onto the very end of the bitstream for reference?
|
|
||||||
int *dibit_p;
|
|
||||||
dibit_p = state->dibit_buf_p - 20; //rewind 20 dibits
|
|
||||||
for (int i = 2140; i < 2160; i++) //2160 for an entire superframe of dibits (Symbols)
|
|
||||||
{
|
|
||||||
dibit = *dibit_p;
|
|
||||||
dibit_p++;
|
|
||||||
p2bit[i*2] = (dibit >> 1) & 1;
|
|
||||||
p2bit[i*2+1] = (dibit & 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_Frame_Scramble (dsd_opts * opts, dsd_state * state)
|
void process_Frame_Scramble (dsd_opts * opts, dsd_state * state)
|
||||||
@@ -385,19 +377,31 @@ void process_ISCH (dsd_opts * opts, dsd_state * state)
|
|||||||
int chan_num = (isch_decoded >> 5) & 0x3;
|
int chan_num = (isch_decoded >> 5) & 0x3;
|
||||||
state->p2_vch_chan_num = chan_num;
|
state->p2_vch_chan_num = chan_num;
|
||||||
|
|
||||||
|
//old rules for entire superframe worth
|
||||||
//determine where the offset should be by first finding TS 0
|
//determine where the offset should be by first finding TS 0
|
||||||
//this rule doesn't seem to work properly on LCCH,
|
// if (chan_num == 0 && isch_loc == 0)
|
||||||
//duke always showed a chan 1 loc 0, so offset 12 - frame
|
// {
|
||||||
if (chan_num == 0 && isch_loc == 0)
|
// state->p2_scramble_offset = 11 - framing_counter;
|
||||||
{
|
// }
|
||||||
state->p2_scramble_offset = 11 - framing_counter;
|
// //find TS1 if TS0 isn't found
|
||||||
}
|
// else if (chan_num == 1 && isch_loc == 0)
|
||||||
//additional rule for odd chan number offset,
|
// {
|
||||||
//fixes duke, and no issues with other samples
|
// state->p2_scramble_offset = 12 - framing_counter;
|
||||||
else if (chan_num == 1 && isch_loc == 0)
|
// }
|
||||||
|
|
||||||
|
//new rules for relative position to the only chan 1 we should see
|
||||||
|
if (chan_num == 1 && isch_loc == 0)
|
||||||
{
|
{
|
||||||
state->p2_scramble_offset = 12 - framing_counter;
|
state->p2_scramble_offset = 12 - framing_counter;
|
||||||
}
|
}
|
||||||
|
else if (chan_num == 1 && isch_loc == 1)
|
||||||
|
{
|
||||||
|
state->p2_scramble_offset = 4 - framing_counter;
|
||||||
|
}
|
||||||
|
else if (chan_num == 1 && isch_loc == 2)
|
||||||
|
{
|
||||||
|
state->p2_scramble_offset = 8 - framing_counter;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -405,9 +409,8 @@ void process_ISCH (dsd_opts * opts, dsd_state * state)
|
|||||||
//if -2(no return value) or -1(fec error)
|
//if -2(no return value) or -1(fec error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// fprintf (stderr, "\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,7 +656,7 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ts_counter = 0; ts_counter < 12; ts_counter++)
|
for (ts_counter = 0; ts_counter < 4; ts_counter++) //12
|
||||||
{
|
{
|
||||||
|
|
||||||
p2_duid[0] = p2bit[0+(ts_counter*360)];
|
p2_duid[0] = p2bit[0+(ts_counter*360)];
|
||||||
@@ -678,15 +681,6 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|||||||
fprintf (stderr,"%s ", getTime());
|
fprintf (stderr,"%s ", getTime());
|
||||||
fprintf (stderr, " P25p2 ");
|
fprintf (stderr, " P25p2 ");
|
||||||
|
|
||||||
if (state->currentslot == 0)
|
|
||||||
{
|
|
||||||
state->currentslot = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state->currentslot = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//print our VCH channel number, or print S for SACCH since its inverted
|
//print our VCH channel number, or print S for SACCH since its inverted
|
||||||
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
|
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
|
||||||
{
|
{
|
||||||
@@ -788,6 +782,16 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|||||||
//add 360 bits to each counter
|
//add 360 bits to each counter
|
||||||
vc_counter = vc_counter + 360;
|
vc_counter = vc_counter + 360;
|
||||||
|
|
||||||
|
//flip slots after each TS processed
|
||||||
|
if (state->currentslot == 0)
|
||||||
|
{
|
||||||
|
state->currentslot = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->currentslot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
END:
|
END:
|
||||||
if (1 == 2)
|
if (1 == 2)
|
||||||
@@ -800,16 +804,23 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|||||||
void processP2 (dsd_opts * opts, dsd_state * state)
|
void processP2 (dsd_opts * opts, dsd_state * state)
|
||||||
{
|
{
|
||||||
state->dmr_stereo = 1;
|
state->dmr_stereo = 1;
|
||||||
state->currentslot = 1;
|
//state->currentslot = 1;
|
||||||
|
|
||||||
p2_dibit_buffer (opts, state);
|
p2_dibit_buffer (opts, state);
|
||||||
|
|
||||||
//look at our ISCH values and determine location in superframe before running frame scramble
|
//look at our ISCH values and determine location in superframe before running frame scramble
|
||||||
for (framing_counter = 0; framing_counter < 11; framing_counter++) //11, or 12
|
for (framing_counter = 0; framing_counter < 4; framing_counter++) //12
|
||||||
{
|
{
|
||||||
process_ISCH (opts, state); //run ISCH in here so we know when to start descramble offset
|
process_ISCH (opts, state); //run ISCH in here so we know when to start descramble offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set initial current slot depending on offset value
|
||||||
|
if (state->p2_scramble_offset % 2)
|
||||||
|
{
|
||||||
|
state->currentslot = 0;
|
||||||
|
}
|
||||||
|
else state->currentslot = 1;
|
||||||
|
|
||||||
//frame_scramble runs lfsr and creates an array of unscrambled bits to pull from
|
//frame_scramble runs lfsr and creates an array of unscrambled bits to pull from
|
||||||
process_Frame_Scramble (opts, state);
|
process_Frame_Scramble (opts, state);
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
/*-------------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------------
|
||||||
* p25p2_vpdu.c
|
* p25p2_vpdu.c
|
||||||
* Phase 2 Variable PDU Handling
|
* Phase 2 Variable PDU (and TSBK PDU) Handling
|
||||||
*
|
*
|
||||||
* LWVMOBILE
|
* LWVMOBILE
|
||||||
* 2022-09 DSD-FME Florida Man Edition
|
* 2022-10 DSD-FME Florida Man Edition
|
||||||
*-----------------------------------------------------------------------------*/
|
*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "dsd.h"
|
#include "dsd.h"
|
||||||
@@ -77,6 +77,70 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//New PDUs added below here as of 10-23-2022
|
||||||
|
|
||||||
|
//SNDCP Data Channel Announcement
|
||||||
|
if (MAC[1+len_a] == 0xD6)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "\n SNDCP Data Channel Announcement ");
|
||||||
|
}
|
||||||
|
|
||||||
|
//MFID90 Group Regroup Add Command
|
||||||
|
if (MAC[1+len_a] == 0x81) //needs MAC message len update, may work same as explicit enc regroup?
|
||||||
|
{
|
||||||
|
fprintf (stderr, "\n MFID90 Group Regroup Add Command ");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Authentication Response - Abbreviated
|
||||||
|
if (MAC[1+len_a] == 0x78)
|
||||||
|
{
|
||||||
|
int res1 = 0; //don't really care about this value, just setting it to zero
|
||||||
|
int source = (MAC[8+len_a] << 16) | (MAC[9+len_a] << 8) | MAC[10+len_a];
|
||||||
|
fprintf (stderr, "\n Authentication Response - Abbreviated \n");
|
||||||
|
fprintf (stderr, " Source [%08d][%06X] ", source, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Authentication Response - Extended
|
||||||
|
if (MAC[1+len_a] == 0xF8)
|
||||||
|
{
|
||||||
|
//only partial data will print on this, do we really care about the SUID?
|
||||||
|
int source = (MAC[5+len_a] << 16) | (MAC[6+len_a] << 8) | MAC[7+len_a];
|
||||||
|
fprintf (stderr, "\n Authentication Response - Extended \n");
|
||||||
|
fprintf (stderr, " Source [%08d][%06X] ", source, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
//RFSS Status Broadcast - Implicit
|
||||||
|
if (MAC[1+len_a] == 0x7A)
|
||||||
|
{
|
||||||
|
int lra = MAC[2+len_a];
|
||||||
|
int lsysid = ((MAC[3+len_a] & 0xF) << 8) | MAC[4+len_a];
|
||||||
|
int rfssid = MAC[5+len_a];
|
||||||
|
int siteid = MAC[6+len_a];
|
||||||
|
int channel = (MAC[7+len_a] << 8) | MAC[8+len_a];
|
||||||
|
int sysclass = MAC[9+len_a];
|
||||||
|
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);
|
||||||
|
process_channel_to_freq (opts, state, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
//RFSS Status Broadcast - Explicit
|
||||||
|
if (MAC[1+len_a] == 0xFA)
|
||||||
|
{
|
||||||
|
int lra = MAC[2+len_a];
|
||||||
|
int lsysid = ((MAC[3+len_a] & 0xF) << 8) | MAC[4+len_a];
|
||||||
|
int rfssid = MAC[5+len_a];
|
||||||
|
int siteid = MAC[6+len_a];
|
||||||
|
int channelt = (MAC[7+len_a] << 8) | MAC[8+len_a];
|
||||||
|
int channelr = (MAC[9+len_a] << 8) | MAC[10+len_a];
|
||||||
|
int sysclass = MAC[11+len_a];
|
||||||
|
fprintf (stderr, "\n RFSS Status Broadcast - Explicit \n");
|
||||||
|
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, channelr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//End New PDUs added
|
||||||
|
|
||||||
//Group Voice Channel Grant (GRP_V_CH_GRANT)
|
//Group Voice Channel Grant (GRP_V_CH_GRANT)
|
||||||
if (MAC[1+len_a] == 0x40)
|
if (MAC[1+len_a] == 0x40)
|
||||||
{
|
{
|
||||||
@@ -156,7 +220,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
|||||||
year, month, day, hour, min, seconds);
|
year, month, day, hour, min, seconds);
|
||||||
fprintf (stderr, " Local Time Offset: %.01f Hours;", offhour);
|
fprintf (stderr, " Local Time Offset: %.01f Hours;", offhour);
|
||||||
//if ist bit is set, then time on system may be considered invalid (i.e., no external time sync)
|
//if ist bit is set, then time on system may be considered invalid (i.e., no external time sync)
|
||||||
if (ist == 1)
|
if (ist % 1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, " Invalid System Time ");
|
fprintf (stderr, " Invalid System Time ");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
|||||||
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
|
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
|
||||||
{
|
{
|
||||||
//fprintf (stderr, " NULL ");
|
//fprintf (stderr, " NULL ");
|
||||||
|
state->p2_is_lcch = 0; //turn flag off here
|
||||||
|
goto END_SMAC;
|
||||||
}
|
}
|
||||||
else //permit MAC_SIGNAL on CRC ERR if -F option called
|
else //permit MAC_SIGNAL on CRC ERR if -F option called
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user