mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
P2 Console Output Change; --change up color coding slightly Disable YSF Sync --frame_ysf variable was never initialized, so some systems would false sync on YSF (YSF never finished, no handling yet)
1680 lines
47 KiB
C
1680 lines
47 KiB
C
/*-------------------------------------------------------------------------------
|
|
* p25_p2.c
|
|
* Phase 2 TDMA Voice Processing
|
|
*
|
|
* original copyrights for portions used below (OP25 DUID table, MAC len table)
|
|
*
|
|
* LWVMOBILE
|
|
* 2022-09 DSD-FME Florida Man Edition
|
|
*-----------------------------------------------------------------------------*/
|
|
/*
|
|
* Copyright (C) 2010 DSD Author
|
|
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
#include "dsd.h"
|
|
|
|
//DUID Look Up Table from OP25
|
|
static const int16_t duid_lookup[256] = {
|
|
0,0,0,-1,0,-1,-1,1,0,-1,-1,4,-1,8,2,-1,
|
|
0,-1,-1,1,-1,1,1,1,-1,3,9,-1,5,-1,-1,1,
|
|
0,-1,-1,10,-1,6,2,-1,-1,3,2,-1,2,-1,2,2,
|
|
-1,3,7,-1,11,-1,-1,1,3,3,-1,3,-1,3,2,-1,
|
|
0,-1,-1,4,-1,6,12,-1,-1,4,4,4,5,-1,-1,4,
|
|
-1,13,7,-1,5,-1,-1,1,5,-1,-1,4,5,5,5,-1,
|
|
-1,6,7,-1,6,6,-1,6,14,-1,-1,4,-1,6,2,-1,
|
|
7,-1,7,7,-1,6,7,-1,-1,3,7,-1,5,-1,-1,15,
|
|
0,-1,-1,10,-1,8,12,-1,-1,8,9,-1,8,8,-1,8,
|
|
-1,13,9,-1,11,-1,-1,1,9,-1,9,9,-1,8,9,-1,
|
|
-1,10,10,10,11,-1,-1,10,14,-1,-1,10,-1,8,2,-1,
|
|
11,-1,-1,10,11,11,11,-1,-1,3,9,-1,11,-1,-1,15,
|
|
-1,13,12,-1,12,-1,12,12,14,-1,-1,4,-1,8,12,-1,
|
|
13,13,-1,13,-1,13,12,-1,-1,13,9,-1,5,-1,-1,15,
|
|
14,-1,-1,10,-1,6,12,-1,14,14,14,-1,14,-1,-1,15,
|
|
-1,13,7,-1,11,-1,-1,15,14,-1,-1,15,-1,15,15,15,
|
|
};
|
|
|
|
//4V and 2V deinterleave schedule
|
|
const int c0[24] = {
|
|
23,5,22,4,21,3,20,2,19,1,18,0,
|
|
17,16,15,14,13,12,11,10,9,7,6
|
|
};
|
|
|
|
const int c1[24] = {
|
|
10,9,8,7,6,5,22,4,21,3,20,2,
|
|
19,1,18,0,17,16,15,14,13,12,11
|
|
};
|
|
|
|
const int c2[24] = {
|
|
3,2,1,0,10,9,8,7,6,5,4
|
|
};
|
|
|
|
const int c3[24] = {
|
|
13,12,11,10,9,8,7,6,5,4,3,2,1,0
|
|
};
|
|
|
|
const int csubset[72] = {
|
|
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,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
|
|
};
|
|
|
|
const int *w;
|
|
|
|
char ambe_fr1[4][24] = {0};
|
|
char ambe_fr2[4][24] = {0};
|
|
char ambe_fr3[4][24] = {0};
|
|
char ambe_fr4[4][24] = {0};
|
|
|
|
//MAC message lengths, from OP25
|
|
static const uint8_t mac_msg_len[256] = {
|
|
0, 7, 8, 7, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //1F
|
|
0, 14, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //2F
|
|
5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //3F
|
|
9, 7, 9, 0, 9, 8, 9, 0, 10, 10, 9, 0, 10, 0, 0, 0, //4F
|
|
0, 0, 0, 0, 9, 7, 0, 0, 10, 0, 7, 0, 10, 8, 14, 7, //5F
|
|
9, 9, 0, 0, 9, 0, 0, 9, 10, 0, 7, 10, 10, 7, 0, 9, //6F
|
|
9, 29, 9, 9, 9, 9, 10, 13, 9, 9, 9, 11, 9, 9, 0, 0, //7F
|
|
8, 0, 0, 7, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9F
|
|
16, 0, 0, 11, 13, 11, 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, //AF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //BF
|
|
11, 0, 0, 8, 15, 12, 15, 32, 12, 12, 0, 27, 14, 29, 29, 32, //CF
|
|
0, 0, 0, 0, 0, 0, 9, 0, 14, 29, 11, 27, 14, 0, 40, 11, //DF //DE = 40? must be multi fragment?
|
|
28, 0, 0, 14, 17, 14, 0, 0, 16, 8, 11, 0, 13, 19, 0, 0, //EF
|
|
0, 0, 16, 14, 0, 0, 12, 0, 22, 0, 11, 13, 11, 0, 15, 0 }; //FF
|
|
|
|
|
|
int ts_counter = 0; //timeslot counter for time slots 0-11
|
|
int p2bit[4320] = {0}; //4320
|
|
int p2lbit[8640] = {0}; //bits generated by lsfr scrambler, doubling up for offset roll-over
|
|
int p2xbit[4320] = {0}; //bits xored from p2bit and p2lbit
|
|
int dibit = 0;
|
|
int vc_counter = 0;
|
|
int fourv_counter = 0;
|
|
int framing_counter = 0;
|
|
|
|
unsigned long long int isch = 0;
|
|
unsigned long long int isch_decoded = 0;
|
|
int p2_duid[8] = {0};
|
|
int16_t duid_decoded = 0;
|
|
int mac_opcode = -1; //initialize to -1
|
|
int mac_offset = -1;
|
|
int mco = -1;
|
|
|
|
int ess_b[2][96] = {0}; //96 bits for 4 - 24 bit ESS_B fields starting bit 168 (RS 44,16,29)
|
|
int ess_a[2][168] = {0}; //ESS_A 1 (96 bit) and 2 (72 bit) fields, starting at bit 168 and bit 266 (RS Parity)
|
|
|
|
int facch[2][156] = {0};
|
|
int facch_rs[2][114] = {0};
|
|
|
|
int sacch[2][180] = {0};
|
|
int sacch_rs[2][132] = {0};
|
|
|
|
//not sure we need this seperation for LCCH, seems to work fine as SACCH
|
|
int lcch[2][180] = {0};
|
|
int lcch_rs[2][132] = {0};
|
|
|
|
//How long is a superframe? What is just one superframe?
|
|
//superframe is 360ms, contains 12 consecutive 30 msec timeslots numbered 0 through 11
|
|
//superframe contains Logical Channel LCH 0 and LCH 1 (LCH 0 - 0,2,4,6,8,11)(LCH 1 - 1,3,5,7,9,10)
|
|
//one ultraframe contains 4 superframes
|
|
|
|
//store an entire p2 superframe worth of dibits into a bit buffer
|
|
void p2_dibit_buffer (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//S-ISCH alternates, so we should start at VC1 right after S-ISCH
|
|
for (int i = 0; i < 2140; i++) //2160 for an entire superframe of dibits (Symbols) //2140 //2120 cut off last ISCH
|
|
{
|
|
//rip dibits directly from the capture bin file instead of getDibit
|
|
if (opts->audio_in_type == 4) //4
|
|
{
|
|
dibit = fgetc(opts->symbolfile);
|
|
//experimental throttle
|
|
useconds_t stime = state->symbol_throttle;
|
|
if (state->use_throttle == 1)
|
|
{
|
|
usleep(stime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dibit = getDibit(opts, state);
|
|
if (opts->inverted_p2 == 1)
|
|
{
|
|
dibit = (dibit ^ 2); //invert dibit here since we are reading it upside down
|
|
}
|
|
}
|
|
|
|
p2bit[i*2] = (dibit >> 1) & 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)
|
|
{
|
|
//The bits of the scramble sequence corresponding to signal bits that are not scrambled or not used are discarded.
|
|
//descramble voice scrambled by LFSR of WACN, SysID, and CC(NAC)
|
|
unsigned long long int seed = 0;
|
|
//below calc is the same as shifting left the required number of bits...neat.
|
|
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
|
|
|
|
for (int i = 0; i < 4320; i++)
|
|
{
|
|
//External LFSR in figure 7.1 BBAC
|
|
|
|
//assign our scramble bit to the array
|
|
p2lbit[i] = (seed >> 43) & 0x1;
|
|
//assign same bit to position +4320 to allow for a rollover with an offset value
|
|
p2lbit[i+4320] = (seed >> 43) & 0x1;
|
|
//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;
|
|
seed = (seed << 1) | bit;
|
|
}
|
|
|
|
for (int i = 0; i < 4300; i++)
|
|
{
|
|
//offset by 20 for sync, then 360 for each ts frame off
|
|
p2xbit[i] = p2bit[i] ^ p2lbit[i+20+(360*state->p2_scramble_offset)];
|
|
}
|
|
|
|
}
|
|
|
|
void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned long long int MAC[24])
|
|
{
|
|
//handle variable content MAC PDUs (Active, Idle, Hangtime, or Signal)
|
|
//use type to specify SACCH or FACCH, so we know if we should invert the currentslot when assigning ids etc
|
|
//get first b1 and b2 values, and first offset value
|
|
//need a lookup table for message length values...aquired one from OP25
|
|
|
|
//b values - 0 = Unique TDMA Message, 1 Phase 1 OSP/ISP abbreviated
|
|
// 2 = Manufacturer Message, 3 Phase 1 OSP/ISP extended/explicit
|
|
|
|
int b_a = MAC[1] >> 6;
|
|
int mco_a = MAC[1] & 0x3F;
|
|
int len_a = 0; //initial on zero, then set equal to len_b after first message rep
|
|
int len_b = mac_msg_len[MAC[1]]; //thinking the lookup is based on the full byte 1
|
|
|
|
int slot = 9;
|
|
if (type == 1) //0 for F, 1 for S
|
|
{
|
|
slot = (state->currentslot ^ 1) & 1; //flip slot internally for SACCH
|
|
}
|
|
else slot = state->currentslot;
|
|
|
|
//init potential second message info
|
|
//this area needs reworking, consider using the DMR 1/2 or 3/4 rate superframe buffer
|
|
int b_b = 0;
|
|
int mco_b = 0;
|
|
|
|
//assigning here if OECI MAC SIGNAL, after passing RS and CRC
|
|
if (state->p2_is_lcch == 1)
|
|
{
|
|
if (slot == 0) state->dmrburstL = 30;
|
|
else state->dmrburstR = 30;
|
|
}
|
|
|
|
//if len is 0, then just skip the check entirely, or greater than 14? See comment below.
|
|
if (len_b == 0 || len_b > 14) //DE had a message length of 40! 40 What!? Way out of bounds on the array!
|
|
{
|
|
goto END_PDU;
|
|
}
|
|
|
|
for (int i = 0; i < 1; i++) //short loop to get both messages if available
|
|
{
|
|
|
|
//Secondary Control Channel Broadcast, Explicit
|
|
if (MAC[1+len_a] == 0xE9)
|
|
{
|
|
int rfssid = MAC[2+len_a];
|
|
int siteid = MAC[3+len_a];
|
|
int channelt = (MAC[4+len_a] << 8) | MAC[5+len_a];
|
|
int channelr = (MAC[6+len_a] << 8) | MAC[7+len_a];
|
|
int sysclass = MAC[8+len_a];
|
|
|
|
if (1 == 1) //state->p2_is_lcch == 1
|
|
{
|
|
fprintf (stderr, "\n Secondary Control Channel Broadcast - Explicit\n");
|
|
fprintf (stderr, " RFSS[%03d] SITE ID [%03X] CHAN-T [%04X] CHAN-R [%04X] SSC [%02X]", rfssid, siteid, channelt, channelr, sysclass);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
}
|
|
|
|
//Secondary Control Channel Broadcast, Implicit
|
|
if (MAC[1+len_a] == 0x79)
|
|
{
|
|
int rfssid = MAC[2+len_a];
|
|
int siteid = MAC[3+len_a];
|
|
int channel1 = (MAC[4+len_a] << 8) | MAC[5+len_a];
|
|
int sysclass1 = MAC[6+len_a];
|
|
int channel2 = (MAC[7+len_a] << 8) | MAC[8+len_a];
|
|
int sysclass2 = MAC[9+len_a];
|
|
if (1 == 1) //state->p2_is_lcch == 1
|
|
{
|
|
fprintf (stderr, "\n Secondary Control Channel Broadcast - Implicit\n");
|
|
fprintf (stderr, " RFSS[%03d] SITE ID [%03X] CHAN1 [%04X] SSC [%02X] CHAN2 [%04X] SSC [%02X]", rfssid, siteid, channel1, sysclass1, channel2, sysclass2);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
}
|
|
|
|
//Group Voice Channel Grant Update - Implicit
|
|
if (MAC[1+len_a] == 0x42)
|
|
{
|
|
int channel1 = (MAC[2+len_a] << 8) | MAC[3+len_a];
|
|
int group1 = (MAC[4+len_a] << 8) | MAC[5+len_a];
|
|
int channel2 = (MAC[6+len_a] << 8) | MAC[7+len_a];
|
|
int group2 = (MAC[8+len_a] << 8) | MAC[9+len_a];
|
|
|
|
fprintf (stderr, "\n Group Voice Channel Grant Update - Implicit");
|
|
fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1);
|
|
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
|
|
|
|
}
|
|
|
|
//Group Voice Channel Grant Update - Explicit
|
|
if (MAC[1+len_a] == 0xC3)
|
|
{
|
|
int svc = MAC[2+len_a];
|
|
int channelt = (MAC[3+len_a] << 8) | MAC[4+len_a];
|
|
int channelr = (MAC[5+len_a] << 8) | MAC[6+len_a];
|
|
int group = (MAC[7+len_a] << 8) | MAC[8+len_a];
|
|
|
|
fprintf (stderr, "\n Group Voice Channel Grant Update - Explicit");
|
|
fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc, channelt, channelr, group, group);
|
|
//maybe, not sure if we want this enabled here or not
|
|
if (slot == 0)
|
|
{
|
|
state->lasttg = group;
|
|
}
|
|
else state->lasttgR = group;
|
|
|
|
}
|
|
|
|
//MFID90 Group Regroup Voice Channel User - Abbreviated
|
|
//this is the one that was playing but had no group or src in tdma6.bin
|
|
if (MAC[1+len_a] == 0x80 && MAC[2+len_a] == 0x90)
|
|
{
|
|
|
|
int gr = (MAC[4+len_a] << 8) | MAC[5+len_a];
|
|
int src = (MAC[6+len_a] << 16) | (MAC[7+len_a] << 8) | MAC[8+len_a];
|
|
fprintf (stderr, "\n VCH %d - Super Group %d SRC %d ", slot, gr, src);
|
|
fprintf (stderr, "MFID90 Group Regroup Voice");
|
|
|
|
if (slot == 0)
|
|
{
|
|
state->lasttg = gr;
|
|
if (src != 0) state->lastsrc = src;
|
|
}
|
|
else
|
|
{
|
|
state->lasttgR = gr;
|
|
if (src != 0) state->lastsrcR = src;
|
|
}
|
|
}
|
|
//MFID90 Group Regroup Voice Channel User - Extended
|
|
if (MAC[1+len_a] == 0xA0 && MAC[2+len_a] == 0x90)
|
|
{
|
|
|
|
int gr = (MAC[5+len_a] << 8) | MAC[6+len_a];
|
|
int src = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a];
|
|
fprintf (stderr, "\n VCH %d - Super Group %d SRC %d ", slot, gr, src);
|
|
fprintf (stderr, "MFID90 Group Regroup Voice");
|
|
|
|
if (slot == 0)
|
|
{
|
|
state->lasttg = gr;
|
|
if (src != 0) state->lastsrc = src;
|
|
}
|
|
else
|
|
{
|
|
state->lasttgR = gr;
|
|
if (src != 0) state->lastsrcR = src;
|
|
}
|
|
}
|
|
|
|
//1 or 21, group voice channel message, abb and ext
|
|
if (MAC[1+len_a] == 0x1 || MAC[1+len_a] == 0x21)
|
|
{
|
|
int svc = MAC[2+len_a];
|
|
int gr = (MAC[3+len_a] << 8) | MAC[4+len_a];
|
|
int src = (MAC[5+len_a] << 16) | (MAC[6+len_a] << 8) | MAC[7+len_a];
|
|
|
|
fprintf (stderr, "\n VCH %d - TG %d SRC %d ", slot, gr, src);
|
|
fprintf (stderr, "Group Voice");
|
|
|
|
if (slot == 0)
|
|
{
|
|
state->lasttg = gr;
|
|
if (src != 0) state->lastsrc = src;
|
|
}
|
|
else
|
|
{
|
|
state->lasttgR = gr;
|
|
if (src != 0) state->lastsrcR = src;
|
|
}
|
|
}
|
|
//1 or 21, group voice channel message, abb and ext
|
|
if (MAC[1+len_a] == 0x2 || MAC[1+len_a] == 0x22)
|
|
{
|
|
int svc = MAC[2+len_a];
|
|
int gr = (MAC[3+len_a] << 16) | (MAC[4+len_a] << 8) | MAC[5+len_a];
|
|
int src = (MAC[6+len_a] << 16) | (MAC[7+len_a] << 8) | MAC[8+len_a];
|
|
|
|
fprintf (stderr, "\n VCH %d - TG %d SRC %d ", slot, gr, src);
|
|
fprintf (stderr, "Unit to Unit Voice");
|
|
|
|
if (slot == 0)
|
|
{
|
|
state->lasttg = gr;
|
|
if (src != 0) state->lastsrc = src;
|
|
}
|
|
else
|
|
{
|
|
state->lasttgR = gr;
|
|
if (src != 0) state->lastsrcR = src;
|
|
}
|
|
}
|
|
//network status broadcast, abbreviated
|
|
if (MAC[1+len_a] == 0x7B)
|
|
{
|
|
//fprintf (stderr, "%s", KCYN);
|
|
int lra = MAC[2+len_a];
|
|
int lwacn = (MAC[3+len_a] << 12) | (MAC[4+len_a] << 4) | ((MAC[5+len_a] & 0xF0) >> 4);
|
|
int lsysid = ((MAC[5+len_a] & 0xF) << 8) | MAC[6+len_a];
|
|
int channel = (MAC[7+len_a] << 8) | MAC[8+len_a];
|
|
int sysclass = MAC[9+len_a];
|
|
int lcolorcode = ((MAC[10+len_a] & 0xF) << 8) | MAC[11+len_a];
|
|
fprintf (stderr, "\n Network Status Broadcast - Abbreviated \n");
|
|
fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X]", lra, lwacn, lsysid, lcolorcode, channel);
|
|
fprintf (stderr, "%s", KNRM);
|
|
if (state->p2_hardset == 0 )
|
|
{
|
|
state->p2_wacn = lwacn;
|
|
state->p2_sysid = lsysid;
|
|
state->p2_cc = lcolorcode;
|
|
}
|
|
|
|
}
|
|
//network status broadcast, extended
|
|
if (MAC[1+len_a] == 0xFB)
|
|
{
|
|
int lra = MAC[2+len_a];
|
|
int lwacn = (MAC[3+len_a] << 12) | (MAC[4+len_a] << 4) | ((MAC[5+len_a] & 0xF0) >> 4);
|
|
int lsysid = ((MAC[5+len_a] & 0xF) << 8) | 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[9+len_a];
|
|
int lcolorcode = ((MAC[12+len_a] & 0xF) << 8) | MAC[13+len_a];
|
|
//fprintf (stderr, "%s", KCYN);
|
|
fprintf (stderr, "\n Network Status Broadcast - Extended \n");
|
|
fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X] CHAN-R [%04X]", lra, lwacn, lsysid, lcolorcode, channelt, channelr);
|
|
fprintf (stderr, "%s", KNRM);
|
|
if (state->p2_hardset == 0 )
|
|
{
|
|
state->p2_wacn = lwacn;
|
|
state->p2_sysid = lsysid;
|
|
state->p2_cc = lcolorcode;
|
|
}
|
|
}
|
|
|
|
//Adjacent Status Broadcast, abbreviated
|
|
if (MAC[1+len_a] == 0x7C)
|
|
{
|
|
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[9+len_a];
|
|
//int lcolorcode = ((MAC[12+len_a] & 0xF) << 8) | MAC[13+len_a];
|
|
if (1 == 1) //state->p2_is_lcch == 1
|
|
{
|
|
//fprintf (stderr, "%s", KCYN);
|
|
fprintf (stderr, "\n Adjacent Status Broadcast - Abbreviated\n");
|
|
fprintf (stderr, " LRA [%02X] RFSS[%03d] SYSID [%03X] CHAN-T [%04X] SSC [%02X]", lra, rfssid, lsysid, channelt, sysclass);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
}
|
|
|
|
//Adjacent Status Broadcast, extended
|
|
if (MAC[1+len_a] == 0xFC)
|
|
{
|
|
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[9+len_a];
|
|
//int lcolorcode = ((MAC[12+len_a] & 0xF) << 8) | MAC[13+len_a];
|
|
if (1 == 1) //state->p2_is_lcch == 1
|
|
{
|
|
//fprintf (stderr, "%s", KCYN);
|
|
fprintf (stderr, "\n Adjacent Status Broadcast - Extended\n");
|
|
fprintf (stderr, " LRA [%02X] RFSS[%03d] SYSID [%03X] CHAN-T [%04X] CHAN-R [%04X] SSC [%02X]", lra, rfssid, lsysid, channelt, channelr, sysclass);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
}
|
|
|
|
//set len_b for next potential message
|
|
len_b = mac_msg_len[MAC[1+len_b]];
|
|
//set len_a as offset for next message if applicable, or exit loop early
|
|
if (len_b != 0 || len_b < 15) //DE had a message length of 40! 40 What!? Way out of bounds on the array!
|
|
{
|
|
len_a = len_b;
|
|
}
|
|
else
|
|
{
|
|
goto END_PDU;
|
|
}
|
|
|
|
}
|
|
|
|
END_PDU:
|
|
state->p2_is_lcch = 0; //toggle off so subsequent things can't trip it again
|
|
//debug printing
|
|
if (opts->payload == 1 && MAC[1] != 0 && MAC[2] != 0) //print only if not a null type
|
|
{
|
|
fprintf (stderr, "%s", KCYN);
|
|
fprintf (stderr, "\n Full MAC vPDU Payload\n ");
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
fprintf (stderr, "[%02llX]", MAC[i]);
|
|
if (i == 11) fprintf (stderr, "\n ");
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
}
|
|
|
|
//MAC PDU 3-bit Opcodes BBAC (8.4.1) p 123:
|
|
//0 - reserved //1 - Mac PTT //2 - Mac End PTT //3 - Mac Idle //4 - Mac Active
|
|
//5 - reserved //6 - Mac Hangtime //7 - reserved //Mac PTT BBAC p80
|
|
|
|
void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180])
|
|
{
|
|
//Figure out which PDU we are looking at, see above info on 8.4.1
|
|
//reorganize bits into bytes and process accordingly
|
|
|
|
unsigned long long int SMAC[24] = {0}; //22.5 bytes for SACCH MAC PDUs
|
|
int byte = 0;
|
|
int k = 0;
|
|
for (int j = 0; j < 22; j++)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
byte = byte << 1;
|
|
byte = byte | payload[k];
|
|
k++;
|
|
}
|
|
SMAC[j] = byte;
|
|
byte = 0; //reset byte
|
|
}
|
|
SMAC[22] = (payload[176] << 7) | (payload[177] << 6) | (payload[178] << 5) | (payload[179] << 4);
|
|
|
|
int opcode = 0;
|
|
opcode = (payload[0] << 2) | (payload[1] << 1) | (payload[2] << 0);
|
|
int mac_offset = 0;
|
|
mac_offset = (payload[3] << 2) | (payload[4] << 1) | (payload[5] << 0);
|
|
int b = 9;
|
|
b = (payload[8] << 1) | (payload[9] << 0); //combined b1 and b2
|
|
int mco_a = 69;
|
|
//mco will tell us the number of octets to use in variable length MAC PDUs, need a table or something
|
|
mco_a = (payload[10] << 5) | (payload[11] << 4) | (payload[12] << 3) | (payload[13] << 2) | (payload[14] << 0) | (payload[15] << 0);
|
|
|
|
//get the second mco after determining first message length, see what second mco is and plan accordingly
|
|
int mco_b = 69;
|
|
|
|
//attempt CRC12 check to validate or reject PDU
|
|
int err = -2;
|
|
if (state->p2_is_lcch == 0)
|
|
{
|
|
int len = 0;
|
|
err = crc12_xb_bridge(payload, 180-12);
|
|
if (err != 0) //CRC Failure, warn or skip.
|
|
{
|
|
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
|
|
{
|
|
//fprintf (stderr, " NULL ");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, " CRC12 ERR S");
|
|
if (state->currentslot == 0) state->dmrburstL = 14;
|
|
else state->dmrburstR = 14;
|
|
goto END_SMAC;
|
|
}
|
|
}
|
|
}
|
|
if (state->p2_is_lcch == 1)
|
|
{
|
|
int len = 0;
|
|
//int len = mac_msg_len[SMAC[1]] * 8;
|
|
//if (len > 164) len = 164; //prevent potential stack smash or other issue.
|
|
len = 164;
|
|
err = crc16_lb_bridge(payload, len);
|
|
if (err != 0) //CRC Failure, warn or skip.
|
|
{
|
|
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
|
|
{
|
|
//fprintf (stderr, " NULL ");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, " CRC16 ERR L");
|
|
state->p2_is_lcch = 0; //turn flag off here
|
|
if (state->currentslot == 0) state->dmrburstL = 14;
|
|
else state->dmrburstR = 14;
|
|
goto END_SMAC;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//remember, slots are inverted here, so set the opposite ones
|
|
//monitor, test, and remove these if they cause issues due to inversion
|
|
if (opcode == 0x0)
|
|
{
|
|
fprintf (stderr, " MAC_SIGNAL ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x1)
|
|
{
|
|
fprintf (stderr, " MAC_PTT ");
|
|
fprintf (stderr, "%s", KGRN);
|
|
//remember, slots are inverted here, so set the opposite ones
|
|
if (state->currentslot == 1)
|
|
{
|
|
//reset fourv_counter on PTT
|
|
state->fourv_counter[0] = 0;
|
|
|
|
state->dmrburstL = 20;
|
|
fprintf (stderr, "\n VCH 0 - ");
|
|
|
|
state->lastsrc = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
|
|
state->lasttg = (SMAC[16] << 8) | SMAC[17];
|
|
|
|
fprintf (stderr, "TG %d ", state->lasttg);
|
|
fprintf (stderr, "SRC %d ", state->lastsrc);
|
|
|
|
|
|
state->payload_algid = SMAC[10];
|
|
state->payload_keyid = (SMAC[11] << 8) | SMAC[12];
|
|
state->payload_miP = (SMAC[1] << 56) | (SMAC[2] << 48) | (SMAC[3] << 40) | (SMAC[4] << 32) |
|
|
(SMAC[5] << 24) | (SMAC[6] << 16) | (SMAC[7] << 8) | (SMAC[8] << 0);
|
|
|
|
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
|
|
fprintf(stderr, " MPTT");
|
|
// fprintf (stderr, " %s", KRED);
|
|
// fprintf (stderr, "ENC");
|
|
}
|
|
|
|
}
|
|
|
|
if (state->currentslot == 0)
|
|
{
|
|
//reset fourv_counter on PTT
|
|
state->fourv_counter[1] = 0;
|
|
|
|
state->payload_algidR = 0;
|
|
|
|
state->dmrburstR = 20;
|
|
fprintf (stderr, "\n VCH 1 - ");
|
|
|
|
state->lastsrcR = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
|
|
state->lasttgR = (SMAC[16] << 8) | SMAC[17];
|
|
|
|
fprintf (stderr, "TG %d ", state->lasttgR);
|
|
fprintf (stderr, "SRC %d ", state->lastsrcR);
|
|
|
|
|
|
state->payload_algidR = SMAC[10];
|
|
state->payload_keyidR = (SMAC[11] << 8) | SMAC[12];
|
|
state->payload_miN = (SMAC[1] << 56) | (SMAC[2] << 48) | (SMAC[3] << 40) | (SMAC[4] << 32) |
|
|
(SMAC[5] << 24) | (SMAC[6] << 16) | (SMAC[7] << 8) | (SMAC[8] << 0);
|
|
|
|
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
|
|
fprintf(stderr, " MPTT");
|
|
// fprintf (stderr, " %s", KRED);
|
|
// fprintf (stderr, "ENC");
|
|
}
|
|
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x2)
|
|
{
|
|
fprintf (stderr, " MAC_END_PTT ");
|
|
fprintf (stderr, "%s", KRED);
|
|
//remember, slots are inverted here, so set the opposite ones
|
|
if (state->currentslot == 1)
|
|
{
|
|
//reset fourv_counter on PTT END
|
|
state->fourv_counter[0] = 0;
|
|
|
|
state->dmrburstL = 23;
|
|
state->payload_algid = 0; //zero this out as well
|
|
state->payload_keyid = 0; //and this
|
|
|
|
fprintf (stderr, "\n VCH 0 - ");
|
|
fprintf (stderr, "TG %d ", state->lasttg);
|
|
fprintf (stderr, "SRC %d ", state->lastsrc);
|
|
|
|
//print it and then zero out
|
|
state->lastsrc = 0;
|
|
state->lasttg = 0;
|
|
}
|
|
if (state->currentslot == 0)
|
|
{
|
|
//reset fourv_counter on PTT END
|
|
state->fourv_counter[1] = 0;
|
|
|
|
state->dmrburstR = 23;
|
|
state->payload_algidR = 0;
|
|
state->payload_keyidR = 0;
|
|
|
|
fprintf (stderr, "\n VCH 1 - ");
|
|
fprintf (stderr, "TG %d ", state->lasttgR);
|
|
fprintf (stderr, "SRC %d ", state->lastsrcR);
|
|
|
|
//print it and then zero out
|
|
state->lastsrcR = 0;
|
|
state->lasttgR = 0;
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x3)
|
|
{
|
|
if (state->currentslot == 1) state->dmrburstL = 24;
|
|
else state->dmrburstR = 24;
|
|
fprintf (stderr, "%s", KMAG);
|
|
fprintf (stderr, " MAC_IDLE ");
|
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x4)
|
|
{
|
|
if (state->currentslot == 1) state->dmrburstL = 21;
|
|
else state->dmrburstR = 21;
|
|
fprintf (stderr, " MAC_ACTIVE ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x6)
|
|
{
|
|
if (state->currentslot == 1) state->dmrburstL = 22;
|
|
else state->dmrburstR = 22;
|
|
fprintf (stderr, " MAC_HANGTIME ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 1, SMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
END_SMAC:
|
|
if (1 == 2)
|
|
{
|
|
//CRC Failure!
|
|
}
|
|
|
|
}
|
|
|
|
void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156])
|
|
{
|
|
//Figure out which PDU we are looking at, see above info on 8.4.1
|
|
//reorganize bits into bytes and process accordingly
|
|
|
|
unsigned long long int FMAC[24] = {0}; //19.5 bytes for FACCH MAC PDUs, add padding to end
|
|
int byte = 0;
|
|
int k = 0;
|
|
for (int j = 0; j < 19; j++)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
byte = byte << 1;
|
|
byte = byte | payload[k];
|
|
k++;
|
|
}
|
|
FMAC[j] = byte;
|
|
byte = 0; //reset byte
|
|
}
|
|
FMAC[19] = (payload[152] << 7) | (payload[153] << 6) | (payload[154] << 5) | (payload[155] << 4);
|
|
|
|
//add padding bytes so we can have a unified variable MAC PDU handler
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
FMAC[i+20] = 0;
|
|
}
|
|
|
|
int opcode = 0;
|
|
opcode = (payload[0] << 2) | (payload[1] << 1) | (payload[2] << 0);
|
|
int mac_offset = 0;
|
|
mac_offset = (payload[3] << 2) | (payload[4] << 1) | (payload[5] << 0);
|
|
|
|
//attempt CRC check to validate or reject PDU
|
|
int err = -2;
|
|
if (state->p2_is_lcch == 0)
|
|
{
|
|
err = crc12_xb_bridge(payload, 156-12);
|
|
if (err != 0) //CRC Failure, warn or skip.
|
|
{
|
|
if (FMAC[1] == 0x0) //NULL PDU Check, pass if NULL
|
|
{
|
|
//fprintf (stderr, " NULL ");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, " CRC12 ERR F");
|
|
if (state->currentslot == 0) state->dmrburstL = 14;
|
|
else state->dmrburstR = 14;
|
|
goto END_FMAC;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Not sure if a MAC Signal will come on a FACCH or not, so disable to prevent falsing
|
|
if (opcode == 0x0)
|
|
{
|
|
fprintf (stderr, " MAC_SIGNAL ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
if (opcode == 0x1)
|
|
{
|
|
|
|
fprintf (stderr, " MAC_PTT ");
|
|
fprintf (stderr, "%s", KGRN);
|
|
if (state->currentslot == 0)
|
|
{
|
|
//reset fourv_counter and dropbyte on PTT
|
|
state->fourv_counter[0] = 0;
|
|
|
|
state->dmrburstL = 20;
|
|
fprintf (stderr, "\n VCH 0 - ");
|
|
|
|
state->lastsrc = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
|
|
state->lasttg = (FMAC[16] << 8) | FMAC[17];
|
|
|
|
fprintf (stderr, "TG %d ", state->lasttg);
|
|
fprintf (stderr, "SRC %d ", state->lastsrc);
|
|
|
|
|
|
state->payload_algid = FMAC[10];
|
|
state->payload_keyid = (FMAC[11] << 8) | FMAC[12];
|
|
state->payload_miP = (FMAC[1] << 56) | (FMAC[2] << 48) | (FMAC[3] << 40) | (FMAC[4] << 32) |
|
|
(FMAC[5] << 24) | (FMAC[6] << 16) | (FMAC[7] << 8) | (FMAC[8] << 0);
|
|
|
|
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
|
|
fprintf(stderr, " MPTT");
|
|
// fprintf (stderr, " %s", KRED);
|
|
// fprintf (stderr, "ENC");
|
|
}
|
|
|
|
}
|
|
|
|
if (state->currentslot == 1)
|
|
{
|
|
//reset fourv_counter and dropbyte on PTT
|
|
state->fourv_counter[1] = 0;
|
|
|
|
state->dmrburstR = 20;
|
|
fprintf (stderr, "\n VCH 1 - ");
|
|
|
|
state->lastsrcR = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
|
|
state->lasttgR = (FMAC[16] << 8) | FMAC[17];
|
|
|
|
fprintf (stderr, "TG %d ", state->lasttgR);
|
|
fprintf (stderr, "SRC %d ", state->lastsrcR);
|
|
|
|
|
|
state->payload_algidR = FMAC[10];
|
|
state->payload_keyidR = (FMAC[11] << 8) | FMAC[12];
|
|
state->payload_miN = (FMAC[1] << 56) | (FMAC[2] << 48) | (FMAC[3] << 40) | (FMAC[4] << 32) |
|
|
(FMAC[5] << 24) | (FMAC[6] << 16) | (FMAC[7] << 8) | (FMAC[8] << 0);
|
|
|
|
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
|
|
fprintf(stderr, " MPTT");
|
|
// fprintf (stderr, " %s", KRED);
|
|
// fprintf (stderr, "ENC");
|
|
}
|
|
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
|
|
}
|
|
if (opcode == 0x2)
|
|
{
|
|
fprintf (stderr, " MAC_END_PTT ");
|
|
fprintf (stderr, "%s", KRED);
|
|
if (state->currentslot == 0)
|
|
{
|
|
//reset fourv_counter and dropbyte on PTT END
|
|
state->fourv_counter[0] = 0;
|
|
|
|
state->dmrburstL = 23;
|
|
state->payload_algid = 0; //zero this out as well
|
|
state->payload_keyid = 0;
|
|
|
|
fprintf (stderr, "\n VCH 0 - ");
|
|
fprintf (stderr, "TG %d ", state->lasttg);
|
|
fprintf (stderr, "SRC %d ", state->lastsrc);
|
|
|
|
//print it and then zero out
|
|
state->lastsrc = 0;
|
|
state->lasttg = 0;
|
|
}
|
|
if (state->currentslot == 1)
|
|
{
|
|
//reset fourv_counter and dropbyte on PTT END
|
|
state->fourv_counter[1] = 0;
|
|
|
|
state->dmrburstR = 23;
|
|
state->payload_algidR = 0; //zero this out as well
|
|
state->payload_keyidR = 0;
|
|
|
|
fprintf (stderr, "\n VCH 1 - ");
|
|
fprintf (stderr, "TG %d ", state->lasttgR);
|
|
fprintf (stderr, "SRC %d ", state->lastsrcR);
|
|
|
|
//print it and then zero out
|
|
state->lastsrcR = 0;
|
|
state->lasttgR = 0;
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x3)
|
|
{
|
|
//what else should we zero out here?
|
|
//disable any of the lines below if issues are observed
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->payload_algid = 0;
|
|
state->payload_keyid = 0;
|
|
state->dmrburstL = 24;
|
|
state->fourv_counter[0] = 0;
|
|
state->lastsrc = 0;
|
|
state->lasttg = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
state->payload_algidR = 0;
|
|
state->payload_keyidR = 0;
|
|
state->dmrburstR = 24;
|
|
state->fourv_counter[1] = 0;
|
|
state->lastsrcR = 0;
|
|
state->lasttgR = 0;
|
|
|
|
}
|
|
fprintf (stderr, " MAC_IDLE ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x4)
|
|
{
|
|
if (state->currentslot == 0) state->dmrburstL = 21;
|
|
else state->dmrburstR = 21;
|
|
fprintf (stderr, " MAC_ACTIVE ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (opcode == 0x6)
|
|
{
|
|
if (state->currentslot == 0) state->dmrburstL = 22;
|
|
else state->dmrburstR = 22;
|
|
fprintf (stderr, " MAC_HANGTIME ");
|
|
fprintf (stderr, "%s", KMAG);
|
|
process_MAC_VPDU(opts, state, 0, FMAC);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
END_FMAC:
|
|
if (1 == 2)
|
|
{
|
|
//CRC Failure!
|
|
}
|
|
|
|
}
|
|
|
|
void process_FACCHc (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//gather and process FACCH w/o scrambling (S-OEMI) so we know what to do with the containing data.
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
facch[state->currentslot][i] = p2bit[i+2+(ts_counter*360)];
|
|
}
|
|
//skip DUID 1
|
|
for (int i = 0; i < 62; i++)
|
|
{
|
|
facch[state->currentslot][i+72] = p2bit[i+76+(ts_counter*360)];
|
|
}
|
|
//skip sync
|
|
for (int i = 0; i < 22; i++)
|
|
{
|
|
facch[state->currentslot][i+134] = p2bit[i+180+(ts_counter*360)];
|
|
}
|
|
//gather FACCH RS parity bits
|
|
for (int i = 0; i < 42; i++)
|
|
{
|
|
facch_rs[state->currentslot][i] = p2bit[i+202+(ts_counter*360)];
|
|
}
|
|
//skip DUID 3
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
facch_rs[state->currentslot][i+42] = p2bit[i+246+(ts_counter*360)];
|
|
}
|
|
|
|
//send payload and parity to ez_rs28_facch for error correction
|
|
int ec = -2;
|
|
ec = ez_rs28_facch (facch[state->currentslot], facch_rs[state->currentslot]);
|
|
|
|
int opcode = 0;
|
|
opcode = (facch[state->currentslot][0] << 2) | (facch[state->currentslot][1] << 1) | (facch[state->currentslot][2] << 0);
|
|
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->dmr_so = opcode;
|
|
}
|
|
else state->dmr_soR = opcode;
|
|
|
|
if (ec > -1) //unsure of upper limit, CRC check will pass or fail from this point
|
|
{
|
|
process_FACCH_MAC_PDU (opts, state, facch[state->currentslot]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, " R-S ERR Fc");
|
|
if (state->currentslot == 0) state->dmrburstL = 13;
|
|
else state->dmrburstR = 13;
|
|
}
|
|
|
|
}
|
|
|
|
void process_FACCHs (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//gather and process FACCH w scrambling (S-OEMI) so we know what to do with the containing data.
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
facch[state->currentslot][i] = p2xbit[i+2+(ts_counter*360)];
|
|
}
|
|
//skip DUID 1
|
|
for (int i = 0; i < 62; i++)
|
|
{
|
|
facch[state->currentslot][i+72] = p2xbit[i+76+(ts_counter*360)];
|
|
}
|
|
//skip sync
|
|
for (int i = 0; i < 22; i++)
|
|
{
|
|
facch[state->currentslot][i+134] = p2xbit[i+180+(ts_counter*360)];
|
|
}
|
|
//gather FACCh RS parity bits
|
|
for (int i = 0; i < 42; i++)
|
|
{
|
|
facch_rs[state->currentslot][i] = p2xbit[i+202+(ts_counter*360)];
|
|
}
|
|
//skip DUID 3
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
facch_rs[state->currentslot][i+42] = p2xbit[i+246+(ts_counter*360)];
|
|
}
|
|
|
|
//send payload and parity to ez_rs28_facch for error correction
|
|
int ec = -2;
|
|
ec = ez_rs28_facch (facch[state->currentslot], facch_rs[state->currentslot]);
|
|
|
|
int opcode = 0;
|
|
opcode = (facch[state->currentslot][0] << 2) | (facch[state->currentslot][1] << 1) | (facch[state->currentslot][2] << 0);
|
|
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->dmr_so = opcode;
|
|
}
|
|
else state->dmr_soR = opcode;
|
|
|
|
if (ec > -1) //unsure of upper limit, CRC check will pass or fail from this point
|
|
{
|
|
process_FACCH_MAC_PDU (opts, state, facch[state->currentslot]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, " R-S ERR Fs");
|
|
if (state->currentslot == 0) state->dmrburstL = 13;
|
|
else state->dmrburstR = 13;
|
|
}
|
|
}
|
|
|
|
void process_SACCHc (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//gather and process SACCH w/o scrambling (I-OEMI) so we know what to do with the containing data.
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
sacch[state->currentslot][i] = p2bit[i+2+(ts_counter*360)];
|
|
}
|
|
//skip DUID 1
|
|
for (int i = 0; i < 108; i++)
|
|
{
|
|
sacch[state->currentslot][i+72] = p2bit[i+76+(ts_counter*360)];
|
|
}
|
|
//start collecting parity
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
sacch_rs[state->currentslot][i] = p2bit[i+184+(ts_counter*360)];
|
|
}
|
|
//skip DUID 3
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
sacch_rs[state->currentslot][i+60] = p2bit[i+246+(ts_counter*360)];
|
|
}
|
|
|
|
//send payload and parity to ez_rs28_sacch for error correction
|
|
int ec = -2;
|
|
ec = ez_rs28_sacch (sacch[0], sacch_rs[0]);
|
|
|
|
int opcode = 0;
|
|
opcode = (sacch[state->currentslot][0] << 2) | (sacch[state->currentslot][1] << 1) | (sacch[state->currentslot][2] << 0);
|
|
|
|
//set inverse true for SACCH
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->dmr_soR = opcode;
|
|
}
|
|
else state->dmr_so = opcode;
|
|
|
|
if (ec > -1) //unsure of upper limit, CRC check will pass or fail from this point
|
|
{
|
|
process_SACCH_MAC_PDU (opts, state, sacch[state->currentslot]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, " R-S ERR Sc");
|
|
if (state->currentslot == 0) state->dmrburstL = 13;
|
|
else state->dmrburstR = 13;
|
|
}
|
|
|
|
}
|
|
|
|
void process_SACCHs (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//gather and process SACCH w scrambling (I-OEMI) so we know what to do with the containing data.
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
sacch[state->currentslot][i] = p2xbit[i+2+(ts_counter*360)];
|
|
}
|
|
//skip DUID 1
|
|
for (int i = 0; i < 108; i++)
|
|
{
|
|
sacch[state->currentslot][i+72] = p2xbit[i+76+(ts_counter*360)];
|
|
}
|
|
//start collecting parity
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
sacch_rs[state->currentslot][i] = p2xbit[i+184+(ts_counter*360)];
|
|
}
|
|
//skip DUID 3
|
|
for (int i = 0; i < 72; i++)
|
|
{
|
|
sacch_rs[state->currentslot][i+60] = p2xbit[i+246+(ts_counter*360)];
|
|
}
|
|
|
|
//send payload and parity to ez_rs28_sacch for error correction
|
|
int ec = -2;
|
|
ec = ez_rs28_sacch (sacch[0], sacch_rs[0]);
|
|
|
|
int opcode = 0;
|
|
opcode = (sacch[state->currentslot][0] << 2) | (sacch[state->currentslot][1] << 1) | (sacch[state->currentslot][2] << 0);
|
|
|
|
//set inverse true for SACCH
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->dmr_soR = opcode;
|
|
}
|
|
else state->dmr_so = opcode;
|
|
|
|
if (ec > -1) //unsure of upper limit, CRC check will pass or fail from this point
|
|
{
|
|
process_SACCH_MAC_PDU (opts, state, sacch[state->currentslot]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, " R-S ERR Ss");
|
|
if (state->currentslot == 0) state->dmrburstL = 13;
|
|
else state->dmrburstR = 13;
|
|
}
|
|
|
|
}
|
|
|
|
void process_ISCH (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
isch = 0;
|
|
for (int i = 0; i < 40; i++)
|
|
{
|
|
isch = isch << 1;
|
|
isch = isch | p2bit[i+320+(360*framing_counter)];
|
|
}
|
|
|
|
if (isch == 0x575D57F7FF) //S-ISCH frame sync, pass;
|
|
{
|
|
//do nothing
|
|
}
|
|
else
|
|
{
|
|
isch_decoded = isch_lookup(isch);
|
|
|
|
if (isch_decoded > 0)
|
|
{
|
|
int uf_count = isch_decoded & 0x3;
|
|
int free = (isch_decoded >> 2) & 0x1;
|
|
int isch_loc = (isch_decoded >> 3) & 0x3;
|
|
int chan_num = (isch_decoded >> 5) & 0x3;
|
|
state->p2_vch_chan_num = chan_num;
|
|
|
|
// fprintf (stderr, "\n I-ISCH = %010llX - Decoded = %02llX -", isch, isch_decoded);
|
|
// fprintf (stderr, " UF Count = %1X - Free = %1X - Loc = %1X Chan = %1X TS = %02d - OFF = %02d", uf_count, free, isch_loc, chan_num, framing_counter, state->p2_scramble_offset);
|
|
|
|
//determine where the offset should be by first finding TS 0
|
|
if (chan_num == 0 && isch_loc == 0)
|
|
{
|
|
//this rule seems to satisfy all conditions I've seen in all samples collected so far
|
|
state->p2_scramble_offset = 11 - framing_counter;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//if -2(no return value) or -1(fec error)
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void process_4V (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
|
|
w = csubset;
|
|
int b = 0;
|
|
int q = 0;
|
|
int r = 0;
|
|
int s = 0;
|
|
int t = 0;
|
|
for (int x = 0; x < 72; x++)
|
|
{
|
|
int ww = *w;
|
|
if (ww == 0)
|
|
{
|
|
b = c0[q];
|
|
q++;
|
|
}
|
|
if (ww == 1)
|
|
{
|
|
b = c1[r];
|
|
r++;
|
|
}
|
|
if (ww == 2)
|
|
{
|
|
b = c2[s];
|
|
s++;
|
|
}
|
|
if (ww == 3)
|
|
{
|
|
b = c3[t];
|
|
t++;
|
|
}
|
|
|
|
ambe_fr1[*w][b] = p2xbit[x+2+vc_counter];
|
|
ambe_fr2[*w][b] = p2xbit[x+76+vc_counter];
|
|
ambe_fr3[*w][b] = p2xbit[x+172+vc_counter];
|
|
ambe_fr4[*w][b] = p2xbit[x+246+vc_counter];
|
|
w++;
|
|
}
|
|
|
|
//collect our ESS_B fragments
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
state->ess_b[state->currentslot][i+(state->fourv_counter[state->currentslot]*24)] =
|
|
p2xbit[i+148+vc_counter];
|
|
}
|
|
|
|
state->fourv_counter[state->currentslot]++;
|
|
//sanity check, reset if greater than 3 (bad signal or tuned away)
|
|
if (state->fourv_counter[state->currentslot] > 3)
|
|
{
|
|
state->fourv_counter[state->currentslot] = 0;
|
|
}
|
|
|
|
if (opts->payload == 1)
|
|
{
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr4, NULL);
|
|
|
|
}
|
|
|
|
void process_ESS (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//collect and process ESS info (MI, Key ID, Alg ID)
|
|
//hand over to (RS 44,16,29) decoder to receive ESS values
|
|
|
|
int payload[96] = {0}; //local storage for ESS_A and ESS_B arrays
|
|
for (int i = 0; i < 96; i++)
|
|
{
|
|
payload[i] = state->ess_b[state->currentslot][i];
|
|
}
|
|
|
|
int parity[168] = {0};
|
|
for (int i = 0; i < 168; i++)
|
|
{
|
|
parity[i] = ess_a[state->currentslot][i];
|
|
}
|
|
|
|
int ec = 69; //initialize with a bad value
|
|
ec = ez_rs28_ess(payload, parity); //working now!
|
|
|
|
int algid = 0;
|
|
for (short i = 0; i < 8; i++)
|
|
{
|
|
algid = algid << 1;
|
|
algid = algid | payload[i];
|
|
}
|
|
|
|
unsigned long long int essb_hex1 = 0;
|
|
unsigned long long int essb_hex2 = 0;
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
essb_hex1 = essb_hex1 << 1;
|
|
essb_hex1 = essb_hex1 | payload[i];
|
|
}
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
essb_hex2 = essb_hex2 << 1;
|
|
essb_hex2 = essb_hex2 | payload[i+32];
|
|
}
|
|
fprintf (stderr, "%s", KYEL);
|
|
|
|
if (opts->payload == 1)
|
|
{
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, " VCH %d - ESS_B %08llX%016llX ERR = %02d", state->currentslot, essb_hex1, essb_hex2, ec);
|
|
}
|
|
|
|
if (ec >= 0 && ec < 15) //corrected up to 14 errors and not -1 failure//
|
|
{
|
|
if (state->currentslot == 0)
|
|
{
|
|
state->payload_algid = (essb_hex1 >> 24) & 0xFF;
|
|
state->payload_keyid = (essb_hex1 >> 8) & 0xFFFF;
|
|
state->payload_miP = ((essb_hex1 & 0xFF) << 56) | ((essb_hex2 & 0xFFFFFFFFFFFFFF00) >> 8);
|
|
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
|
|
{
|
|
fprintf (stderr, "\n VCH 0 -");
|
|
fprintf (stderr, " ALG ID 0x%02X", state->payload_algid);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
|
|
fprintf(stderr, " ESSB");
|
|
}
|
|
|
|
}
|
|
if (state->currentslot == 1)
|
|
{
|
|
state->payload_algidR = (essb_hex1 >> 24) & 0xFF;
|
|
state->payload_keyidR = (essb_hex1 >> 8) & 0xFFFF;
|
|
state->payload_miN = ((essb_hex1 & 0xFF) << 56) | ((essb_hex2 & 0xFFFFFFFFFFFFFF00) >> 8);
|
|
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
|
|
{
|
|
fprintf (stderr, "\n VCH 1 -");
|
|
fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR);
|
|
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
|
|
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
|
|
fprintf(stderr, " ESSB");
|
|
}
|
|
|
|
}
|
|
}
|
|
if (ec == -1 || ec >= 15)
|
|
{
|
|
//ESS R-S Failure
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
|
|
state->fourv_counter[state->currentslot] = 0; //reset after processing
|
|
|
|
}
|
|
|
|
void process_2V (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
|
|
w = csubset;
|
|
int b = 0;
|
|
int q = 0;
|
|
int r = 0;
|
|
int s = 0;
|
|
int t = 0;
|
|
for (int x = 0; x < 72; x++)
|
|
{
|
|
int ww = *w;
|
|
if (ww == 0)
|
|
{
|
|
b = c0[q];
|
|
q++;
|
|
}
|
|
if (ww == 1)
|
|
{
|
|
b = c1[r];
|
|
r++;
|
|
}
|
|
if (ww == 2)
|
|
{
|
|
b = c2[s];
|
|
s++;
|
|
}
|
|
if (ww == 3)
|
|
{
|
|
b = c3[t];
|
|
t++;
|
|
}
|
|
|
|
ambe_fr1[*w][b] = p2xbit[x+2+vc_counter];
|
|
ambe_fr2[*w][b] = p2xbit[x+76+vc_counter];
|
|
w++;
|
|
}
|
|
|
|
//collect ESS_A and then run process_ESS
|
|
for (short i = 0; i < 96; i++)
|
|
{
|
|
ess_a[state->currentslot][i] = p2xbit[i+148+vc_counter];
|
|
}
|
|
|
|
for (short i = 0; i < 72; i++) //load up ESS_A 2
|
|
{
|
|
ess_a[state->currentslot][i+96] = p2xbit[i+246+vc_counter];
|
|
}
|
|
|
|
if (opts->payload == 1)
|
|
{
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
|
|
|
process_ESS(opts, state);
|
|
|
|
}
|
|
|
|
//P2 Data Unit ID
|
|
void process_P2_DUID (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//DUID exist on all P25p2 frames, need to check this so we can process the TS frame properly
|
|
vc_counter = 0;
|
|
int err_counter = 0;
|
|
|
|
//add time to mirror printFrameSync
|
|
time_t now;
|
|
char * getTime(void) //get pretty hh:mm:ss timestamp
|
|
{
|
|
time_t t = time(NULL);
|
|
|
|
char * curr;
|
|
char * stamp = asctime(localtime( & t));
|
|
|
|
curr = strtok(stamp, " ");
|
|
curr = strtok(NULL, " ");
|
|
curr = strtok(NULL, " ");
|
|
curr = strtok(NULL, " ");
|
|
|
|
return curr;
|
|
}
|
|
|
|
for (ts_counter = 0; ts_counter < 12; ts_counter++)
|
|
{
|
|
|
|
p2_duid[0] = p2bit[0+(ts_counter*360)];
|
|
p2_duid[1] = p2bit[1+(ts_counter*360)];
|
|
p2_duid[2] = p2bit[74+(ts_counter*360)];
|
|
p2_duid[3] = p2bit[75+(ts_counter*360)];
|
|
p2_duid[4] = p2bit[244+(ts_counter*360)];
|
|
p2_duid[5] = p2bit[245+(ts_counter*360)];
|
|
p2_duid[6] = p2bit[318+(ts_counter*360)];
|
|
p2_duid[7] = p2bit[319+(ts_counter*360)];
|
|
|
|
//process p2_duid with (8,4,4) encoding/decoding
|
|
int p2_duid_complete = 0;
|
|
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);
|
|
}
|
|
}
|
|
else if (duid_decoded == 6)
|
|
{
|
|
fprintf (stderr, " 2V");
|
|
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_2V (opts, state);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
//fprintf (stderr, " LCCH TDMA CC"); //w/o scrambling OECI
|
|
// if (state->currentslot == 0) state->dmrburstL = 30;
|
|
// else state->dmrburstR = 30;
|
|
state->p2_is_lcch = 1;
|
|
process_SACCHc(opts, state);
|
|
}
|
|
else if (duid_decoded == 4)
|
|
{
|
|
fprintf (stderr, " LCCH Sc"); //w/ scrambling
|
|
// if (state->currentslot == 0) state->dmrburstL = 31;
|
|
// else state->dmrburstR = 31;
|
|
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)
|
|
{
|
|
state->p2_is_lcch = 1;
|
|
process_SACCHs(opts, state);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, " DUID ERR %d", duid_decoded);
|
|
if (state->currentslot == 0) state->dmrburstL = 12;
|
|
else state->dmrburstR = 12;
|
|
err_counter++;
|
|
}
|
|
if (err_counter > 1) //&& opts->aggressive_framesync == 1
|
|
{
|
|
//zero out values when errs accumulate in DUID
|
|
//most likely cause will be signal drop or tuning away
|
|
state->payload_algid = 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;
|
|
}
|
|
//since we are in a while loop, run ncursesPrinter here.
|
|
if (opts->use_ncurses_terminal == 1)
|
|
{
|
|
ncursesPrinter(opts, state);
|
|
}
|
|
//add 360 bits to each counter
|
|
vc_counter = vc_counter + 360;
|
|
|
|
}
|
|
END:
|
|
if (1 == 2)
|
|
{
|
|
//go directly to END if 2 consecutive DUID errors occur
|
|
}
|
|
|
|
}
|
|
|
|
void processP2 (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
//hard code here for ease of use while figuring this out
|
|
//295 samples
|
|
// state->p2_wacn = 0xBEE00; //BEE00
|
|
// state->p2_sysid = 0x295; //39A
|
|
// state->p2_cc = 0x290; //399
|
|
|
|
//adp_tdma.bin and NJ samples
|
|
// state->p2_wacn = 0xBEE00; //BEE00
|
|
// state->p2_sysid = 0x39A; //39A //56C
|
|
// state->p2_cc = 0x399; //399 //561
|
|
|
|
//barrow samples
|
|
// state->p2_wacn = 0xBEE00; //BEE00
|
|
// state->p2_sysid = 0x56C; //39A //56C
|
|
// state->p2_cc = 0x561; //399 //561
|
|
|
|
state->dmr_stereo = 1; //flag on now and flag off on exit
|
|
state->currentslot = 1; //start on 1, initial flip will make it zero again
|
|
|
|
//collect and store a superframe worth of dibits for now, may change later to just 2 TS frames
|
|
p2_dibit_buffer (opts, state);
|
|
|
|
//look at our ISCH values and determine location in superframe before running frame scramble
|
|
//12 is really the s-isch that initiated this, I just tacked it onto the very end for no reason
|
|
for (framing_counter = 0; framing_counter < 11; framing_counter++) //11, or 12
|
|
{
|
|
process_ISCH (opts, state); //run ISCH in here so we know when to start descramble offset
|
|
}
|
|
|
|
//frame_scramble runs lfsr and creates an array of unscrambled bits to pull from
|
|
process_Frame_Scramble (opts, state);
|
|
|
|
//process DUID will run through all collected frames and handle them appropriately
|
|
process_P2_DUID (opts, state);
|
|
state->dmr_stereo = 0; //flag off
|
|
state->p2_is_lcch = 0; //flag off
|
|
fprintf (stderr, "\n"); //print a line break at the end
|
|
}
|