8 Commits
446 ... 454

Author SHA1 Message Date
lwvmobile
0635ab7121 Update README.md 2022-12-27 05:31:04 -05:00
lwvmobile
a0d9e349c2 TSBK NET_STS_BCST Last Block Fix; Protect Block; 2022-11-02 01:40:45 -04:00
lwvmobile
7ca65cf687 Call History Fix & Timestamp; Cap+ VLC Fix; 2022-11-01 03:54:10 -04:00
lwvmobile
b4a0e2e9f3 P2 4V/2V Deinterleave Fix; Errs now C0 and C1; 2022-10-25 19:21:57 -04:00
lwvmobile
73f0d5df44 P25 TSBK Bug Fix; Add More P25 PDUs; 2022-10-23 21:36:06 -04:00
lwvmobile
b003d0a210 Merge pull request #90 from KuzVlad/fix_lfsr
fixed function signature
2022-10-23 15:20:45 -04:00
KuzVlad
83f390ba88 fixed function signature 2022-10-23 13:13:05 +03:00
lwvmobile
c8aafb1be0 P25 P2 Frame Stabilization and Tweaks 2022-10-22 18:45:25 -04:00
11 changed files with 416 additions and 331 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.[ao]
*.so*
*.dylib
build

View File

@@ -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)

View File

@@ -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();

View File

@@ -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,38 +2121,13 @@ 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"); //Full
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
if (opts->payload == 1) if (opts->payload == 1)
{ {
fprintf (stderr, "%s", KCYN); fprintf (stderr, "%s", KCYN);
@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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,38 +115,47 @@ 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)
{ {
long int wacn = (tsbk_byte[3] << 12) | (tsbk_byte[4] << 4) | (tsbk_byte[5] >> 4);;
int sysid = ((tsbk_byte[5] & 0xF) << 8) | tsbk_byte[6];
int channel = (tsbk_byte[7] << 8) | tsbk_byte[8];
fprintf (stderr, "%s",KMAG);
fprintf (stderr, "\n Network Status Broadcast TSBK - Abbreviated \n");
fprintf (stderr, " WACN [%05lX] SYSID [%03X] NAC [%03llX]", wacn, sysid, state->p2_cc);
state->p25_cc_freq = process_channel_to_freq(opts, state, channel);
//only set IF these values aren't already hard set by the user //only set IF these values aren't already hard set by the user
if (state->p2_hardset == 0) if (state->p2_hardset == 0)
{ {
state->p2_wacn = (tsbk_byte[3] << 12) | (tsbk_byte[4] << 4) | (tsbk_byte[5] >> 4); state->p2_wacn = wacn;
state->p2_sysid = ((tsbk_byte[5] & 0xF) << 8) | tsbk_byte[6]; state->p2_sysid = sysid;
int channel = (tsbk_byte[7] << 8) | tsbk_byte[8];
fprintf (stderr, "%s",KMAG);
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);
state->p25_cc_freq = process_channel_to_freq(opts, state, channel);
if (opts->payload == 1)
{
fprintf (stderr, "%s",KCYN);
fprintf (stderr, "\n P25 PDU Payload ");
for (i = 0; i < 12; i++)
{
fprintf (stderr, "[%02X]", tsbk_byte[i]);
}
}
fprintf (stderr, "%s ", KNRM);
} }
if (opts->payload == 1)
{
fprintf (stderr, "%s",KCYN);
fprintf (stderr, "\n P25 PDU Payload ");
for (i = 0; i < 12; i++)
{
fprintf (stderr, "[%02X]", tsbk_byte[i]);
}
}
fprintf (stderr, "%s ", KNRM);
} }
//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");
} }

View File

@@ -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,57 +92,49 @@ 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);
//dibit inversion handled internally by getDibit if sync type is inverted //dibit inversion handled internally by getDibit if sync type is inverted
p2bit[i*2] = (dibit >> 1) & 1; p2bit[i*2] = (dibit >> 1) & 1;
p2bit[i*2+1] = (dibit & 1); p2bit[i*2+1] = (dibit & 1);
} }
//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)
{ {
//The bits of the scramble sequence corresponding to signal bits that are not scrambled or not used are discarded. //The bits of the scramble sequence corresponding to signal bits that are not scrambled or not used are discarded.
//descramble frame scrambled by LFSR of WACN, SysID, and CC(NAC) //descramble frame scrambled by LFSR of WACN, SysID, and CC(NAC)
unsigned long long int seed = 0; unsigned long long int seed = 0;
//below calc is the same as shifting left the required number of bits. //below calc is the same as shifting left the required number of bits.
seed = ( (state->p2_wacn * 16777216) + (state->p2_sysid * 4096) + state->p2_cc ); seed = ( (state->p2_wacn * 16777216) + (state->p2_sysid * 4096) + state->p2_cc );
unsigned long long int bit = 1; //temp bit for storage during LFSR operation unsigned long long int bit = 1; //temp bit for storage during LFSR operation
for (int i = 0; i < 4320; i++) for (int i = 0; i < 4320; i++)
{ {
//External LFSR in figure 7.1 BBAC //External LFSR in figure 7.1 BBAC
//assign our scramble bit to the array //assign our scramble bit to the array
p2lbit[i] = (seed >> 43) & 0x1; p2lbit[i] = (seed >> 43) & 0x1;
//assign same bit to position +4320 to allow for a rollover with an offset value //assign same bit to position +4320 to allow for a rollover with an offset value
p2lbit[i+4320] = (seed >> 43) & 0x1; p2lbit[i+4320] = (seed >> 43) & 0x1;
//compute our next scramble bit and shift the seed register and append bit to LSB //compute our next scramble bit and shift the seed register and append bit to LSB
bit = ((seed >> 33) ^ (seed >> 19) ^ (seed >> 14) ^ (seed >> 8) ^ (seed >> 3) ^ (seed >> 43)) & 0x1; bit = ((seed >> 33) ^ (seed >> 19) ^ (seed >> 14) ^ (seed >> 8) ^ (seed >> 3) ^ (seed >> 43)) & 0x1;
seed = (seed << 1) | bit; seed = (seed << 1) | bit;
} }
for (int i = 0; i < 4300; i++) for (int i = 0; i < 4300; i++)
{ {
//offset by 20 for sync, then 360 for each ts frame off from start of superframe //offset by 20 for sync, then 360 for each ts frame off from start of superframe
p2xbit[i] = p2bit[i] ^ p2lbit[i+20+(360*state->p2_scramble_offset)]; p2xbit[i] = p2bit[i] ^ p2lbit[i+20+(360*state->p2_scramble_offset)];
} }
} }
@@ -363,11 +355,11 @@ void process_SACCHs (dsd_opts * opts, dsd_state * state)
void process_ISCH (dsd_opts * opts, dsd_state * state) void process_ISCH (dsd_opts * opts, dsd_state * state)
{ {
isch = 0; isch = 0;
for (int i = 0; i < 40; i++) for (int i = 0; i < 40; i++)
{ {
isch = isch << 1; isch = isch << 1;
isch = isch | p2bit[i+320+(360*framing_counter)]; isch = isch | p2bit[i+320+(360*framing_counter)];
} }
if (isch == 0x575D57F7FF) //S-ISCH frame sync, pass; if (isch == 0x575D57F7FF) //S-ISCH frame sync, pass;
{ {
@@ -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,140 +656,141 @@ 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)];
p2_duid[1] = p2bit[1+(ts_counter*360)]; p2_duid[1] = p2bit[1+(ts_counter*360)];
p2_duid[2] = p2bit[74+(ts_counter*360)]; p2_duid[2] = p2bit[74+(ts_counter*360)];
p2_duid[3] = p2bit[75+(ts_counter*360)]; p2_duid[3] = p2bit[75+(ts_counter*360)];
p2_duid[4] = p2bit[244+(ts_counter*360)]; p2_duid[4] = p2bit[244+(ts_counter*360)];
p2_duid[5] = p2bit[245+(ts_counter*360)]; p2_duid[5] = p2bit[245+(ts_counter*360)];
p2_duid[6] = p2bit[318+(ts_counter*360)]; p2_duid[6] = p2bit[318+(ts_counter*360)];
p2_duid[7] = p2bit[319+(ts_counter*360)]; p2_duid[7] = p2bit[319+(ts_counter*360)];
//process p2_duid with (8,4,4) encoding/decoding //process p2_duid with (8,4,4) encoding/decoding
int p2_duid_complete = 0; int p2_duid_complete = 0;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{
p2_duid_complete = p2_duid_complete << 1;
p2_duid_complete = p2_duid_complete | p2_duid[i];
}
duid_decoded = duid_lookup[p2_duid_complete];
fprintf (stderr, "\n");
fprintf (stderr,"%s ", getTime());
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
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
{
fprintf (stderr, "VCH 0 ");
}
else if (state->currentslot == 1 && duid_decoded != 3 && duid_decoded != 12)
{
fprintf (stderr, "VCH 1 ");
}
else fprintf (stderr, "VCH S ");
if (duid_decoded == 0)
{
fprintf (stderr, " 4V %d", state->fourv_counter[state->currentslot]+1);
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{ {
process_4V (opts, state); p2_duid_complete = p2_duid_complete << 1;
p2_duid_complete = p2_duid_complete | p2_duid[i];
} }
} duid_decoded = duid_lookup[p2_duid_complete];
else if (duid_decoded == 6)
{ fprintf (stderr, "\n");
fprintf (stderr, " 2V"); fprintf (stderr,"%s ", getTime());
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 && fprintf (stderr, " P25p2 ");
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
//print our VCH channel number, or print S for SACCH since its inverted
if (state->currentslot == 0 && duid_decoded != 3 && duid_decoded != 12)
{ {
process_2V (opts, state); fprintf (stderr, "VCH 0 ");
} }
} else if (state->currentslot == 1 && duid_decoded != 3 && duid_decoded != 12)
else if (duid_decoded == 3)
{
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{ {
process_SACCHs(opts, state); fprintf (stderr, "VCH 1 ");
} }
} else fprintf (stderr, "VCH S ");
else if (duid_decoded == 12)
{ if (duid_decoded == 0)
process_SACCHc(opts, state);
}
else if (duid_decoded == 15)
{
process_FACCHc(opts, state);
}
else if (duid_decoded == 9)
{
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{ {
process_FACCHs(opts, state); fprintf (stderr, " 4V %d", state->fourv_counter[state->currentslot]+1);
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{
process_4V (opts, state);
}
} }
} else if (duid_decoded == 6)
else if (duid_decoded == 13) {
{ fprintf (stderr, " 2V");
state->p2_is_lcch = 1; if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
process_SACCHc(opts, state); state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
} {
else if (duid_decoded == 4) process_2V (opts, state);
{ }
fprintf (stderr, " LCCH Sc"); //w/ scrambling }
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 && else if (duid_decoded == 3)
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF) {
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{
process_SACCHs(opts, state);
}
}
else if (duid_decoded == 12)
{
process_SACCHc(opts, state);
}
else if (duid_decoded == 15)
{
process_FACCHc(opts, state);
}
else if (duid_decoded == 9)
{
if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
{
process_FACCHs(opts, state);
}
}
else if (duid_decoded == 13)
{ {
state->p2_is_lcch = 1; state->p2_is_lcch = 1;
process_SACCHs(opts, state); process_SACCHc(opts, state);
} }
} else if (duid_decoded == 4)
else {
{ fprintf (stderr, " LCCH Sc"); //w/ scrambling
fprintf (stderr, " DUID ERR %d", duid_decoded); if (state->p2_wacn != 0 && state->p2_cc != 0 && state->p2_sysid != 0 &&
if (state->currentslot == 0) state->dmrburstL = 12; state->p2_wacn != 0xFFFFF && state->p2_cc != 0xFFF && state->p2_sysid != 0xFFF)
else state->dmrburstR = 12; {
err_counter++; state->p2_is_lcch = 1;
} process_SACCHs(opts, state);
if (err_counter > 1) //&& opts->aggressive_framesync == 1 }
{ }
//zero out values when errs accumulate in DUID else
//most likely cause will be signal drop or tuning away {
state->payload_algid = 0; fprintf (stderr, " DUID ERR %d", duid_decoded);
state->payload_keyid = 0; if (state->currentslot == 0) state->dmrburstL = 12;
state->payload_algidR = 0; else state->dmrburstR = 12;
state->payload_keyidR = 0; err_counter++;
state->lastsrc = 0; }
state->lastsrcR = 0; if (err_counter > 1) //&& opts->aggressive_framesync == 1
state->lasttg = 0; {
state->lasttgR = 0; //zero out values when errs accumulate in DUID
state->p2_is_lcch = 0; //most likely cause will be signal drop or tuning away
state->fourv_counter[0] = 0; state->payload_algid = 0;
state->fourv_counter[1] = 0; state->payload_keyid = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->lastsrc = 0;
state->lastsrcR = 0;
state->lasttg = 0;
state->lasttgR = 0;
state->p2_is_lcch = 0;
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
goto END; goto END;
} }
//since we are in a while loop, run ncursesPrinter here. //since we are in a while loop, run ncursesPrinter here.
if (opts->use_ncurses_terminal == 1) if (opts->use_ncurses_terminal == 1)
{ {
ncursesPrinter(opts, state); ncursesPrinter(opts, 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:
@@ -800,22 +804,29 @@ 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);
//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;
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }

View File

@@ -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 ");
} }

View File

@@ -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
{ {