5 Commits
446 ... 451

Author SHA1 Message Date
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
10 changed files with 344 additions and 241 deletions

4
.gitignore vendored Normal file
View File

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

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

@@ -2747,7 +2747,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) )

View File

@@ -65,16 +65,39 @@ 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];
/*
___)__|_
.-*' '*-,
/ /| |\ \
; /_| |_\ ;
; |\ /| ;
; | ''--...--'' | ;
\ ''---.....--'' /
''*-.,_______,.-*' BOO!
*/
// char * FM_bannerN[9] = {
// " ESC or Arrow Keys For Menu ",
// " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ ",
// " ██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝ ",
// " ██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ",
// " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
// " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗ ",
// " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝ ",
// " ",
// " "
// };
char * FM_bannerN[9] = { char * FM_bannerN[9] = {
" ESC or Arrow Keys For Menu ", " ESC or Arrow Keys For Menu Happy Halloween! ___)__|_ ",
" ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ ", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗ .-*' '*-, ",
" ██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝ ", " ██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝; /_| |_\\ ;",
" ██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ", " ██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ; |\\ /| ;",
" ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ", " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ; | ''--...--'' | ; ",
" ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗ ", " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗ \\ ''---.....--'' / ",
" ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝ ", " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝ ''*-.,_______,.-*' ",
" ", " Happy Halloween ",
" " " "
}; };
char * SyncTypes[44] = { char * SyncTypes[44] = {
@@ -152,8 +175,8 @@ char * DMRBusrtTypes[32] = {
"VOICE LDU", "VOICE LDU",
"TDU/TDULC", "TDU/TDULC",
"TSBK", "TSBK",
"MAC_SIGNAL", "MAC SIGNAL",
"MAC_SIGNAL" "MAC SIGNAL"
}; };
@@ -1910,13 +1933,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
if (opts->ncurses_compact == 0) if (opts->ncurses_compact == 0)
{ {
attron(COLOR_PAIR(6)); //6 attron(COLOR_PAIR(1)); //6
for (short int i = 0; i < 7; i++) for (short int i = 0; i < 7; i++)
{ {
printw("%s \n", FM_bannerN[i]); printw("%s \n", FM_bannerN[i]);
} }
printw (" https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n"); printw (" https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n");
printw (" Github Build Version: %s \n", GIT_TAG); //printw (" Github Build Version: %s \n", GIT_TAG);
printw (" Github Build Version: %s \n", "1313"); //probably better than the first number I thought of
attroff(COLOR_PAIR(6)); //6 attroff(COLOR_PAIR(6)); //6
// printw ("--Build Info------------------------------------------------------------------\n"); // printw ("--Build Info------------------------------------------------------------------\n");
// printw ("| https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n"); //http link // printw ("| https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n"); //http link

View File

@@ -1,9 +1,9 @@
/*------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------
* 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"
@@ -19,16 +19,14 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
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
//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 +47,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 +66,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 +82,10 @@ 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,
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];
@@ -110,7 +100,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
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 //Don't run NET_STS out of this, or will set wrong NAC/CC
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 if (err == 0 && ec == 0 && PDU[1] != 0x7B && PDU[1] != 0x49 && PDU[1] != 0x45) //0x49 is telephone grant, 0x46 Unit to Unit Channel Answer Request (seems bogus)
{ {
fprintf (stderr, "%s",KMAG); fprintf (stderr, "%s",KMAG);
process_MAC_VPDU(opts, state, 0, PDU); process_MAC_VPDU(opts, state, 0, PDU);
@@ -149,7 +139,12 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
//reset for next rep //reset for next rep
ec = -2; ec = -2;
checksum = -2; err = -2;
//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,30 +31,30 @@ 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] = {
10,9,8,7,6,5,22,4,21,3,20,2, 10,9,8,7,6,5,22,4,21,3,20,2,
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,29 +377,40 @@ 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
{ {
//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
{ {