NXDN Trunking Tweaks and Misc Tweaks;

This commit is contained in:
lwvmobile 2023-03-02 22:13:45 -05:00
parent 3102770353
commit 54c75e20c9
4 changed files with 147 additions and 103 deletions

View File

@ -2263,8 +2263,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("\n");
printw ("| ");
printw ("TGT: [%05d] ", tgn);
printw ("SRC: [%05d] ", src);
printw ("TGT: [%5d] ", tgn);
printw ("SRC: [%5d] ", src);
if (state->nxdn_alias_block_segment[0][0] > 0)
{
printw ("ALIAS: [");
@ -2302,6 +2302,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (state->nxdn_cipher_type == 0x2 && state->carrier == 1)
{
attron(COLOR_PAIR(1));
printw ("IV: [%016llX] ", state->payload_miN);
attron(COLOR_PAIR(2));
printw ("DES-OFB ");
@ -2310,6 +2311,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (state->nxdn_cipher_type == 0x3 && state->carrier == 1)
{
attron(COLOR_PAIR(1));
printw ("IV: [%016llX] ", state->payload_miN);
attron(COLOR_PAIR(2));
printw ("AES-256 ");
@ -2908,8 +2910,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (lls == 28 || lls == 29)
{
printw ("RAN [%02lld] ", call_matrix[9-j][1]);
printw ("TG [%05lld] ", call_matrix[9-j][4]);
printw ("RID [%05lld] ", call_matrix[9-j][2]);
printw ("TG [%5lld] ", call_matrix[9-j][4]);
printw ("RID [%5lld] ", call_matrix[9-j][2]);
}
//dPMR
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)

View File

@ -42,7 +42,8 @@ static const int PARITY[] = {
//decoding functions here
void nxdn_descramble(uint8_t dibits[], int len)
{
for (int i=0; i<sizeof(scramble_t); i++) {
for (int i=0; i<len; i++)
{
if (scramble_t[i] >= len)
break;
dibits[scramble_t[i]] ^= 0x2; // invert sign of scrambled dibits
@ -119,7 +120,7 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
}
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, trellis_buf);
// else if (opts->payload == 1) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
if (opts->payload == 1)
{
@ -137,10 +138,16 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
//new sacch
void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
{
uint8_t deperm[60];
uint8_t depunc[72];
uint8_t trellis_buf[32];
uint8_t answer[26];
//see about initializing these variables
uint8_t deperm[60];
uint8_t depunc[72];
uint8_t trellis_buf[32];
uint8_t answer[26];
memset (deperm, 0, sizeof(deperm));
memset (depunc, 0, sizeof(depunc));
memset (trellis_buf, 0, sizeof(trellis_buf));
memset (answer, 0, sizeof(answer));
int o = 0;
uint8_t crc = 0; //value computed by crc6 on payload
uint8_t check = 0; //value pulled from last 6 bits
@ -186,7 +193,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
}
CNXDNConvolution_start();
for (int i = 0U; i < 40U; i++)
for (int i = 0U; i < 36U; i++) //40
{
s0 = temp[(2*i)];
s1 = temp[(2*i)+1];
@ -195,7 +202,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
}
//stored as 5 bytes, will need to convert to trellis_buf after running
CNXDNConvolution_chainback(m_data, 36U);
CNXDNConvolution_chainback(m_data, 32U); //36
for(int i = 0; i < 4; i++)
{
@ -230,6 +237,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
}
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch);
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, nsf_sacch);
if (opts->payload == 1)
{
@ -398,6 +406,7 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
//NXDN_Elements_Content_decode(opts, state, 1, trellis_buf);
NXDN_Elements_Content_decode(opts, state, 1, f2u_message_buffer);
}
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, f2u_message_buffer);
if (opts->payload == 1)
{
@ -495,6 +504,7 @@ void nxdn_deperm_cac(dsd_opts * opts, dsd_state * state, uint8_t bits[300])
fprintf (stderr, " CAC ");
NXDN_Elements_Content_decode(opts, state, 1, cac_message_buffer);
}
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, cac_message_buffer);
if (opts->payload == 1)
{
@ -518,7 +528,7 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType)
if (MessageType == 0x10) fprintf(stderr, " IDLE");
else if (MessageType == 0x11) fprintf(stderr, " DISC"); //disconnect
else if (MessageType == 0x01) fprintf(stderr, " VCALL");
else if (MessageType == 0x03) fprintf(stderr, " VCALL IV");
else if (MessageType == 0x03) fprintf(stderr, " VCALL_IV");
else if (MessageType == 0x07) fprintf(stderr, " TX_REL_EX");
else if (MessageType == 0x08) fprintf(stderr, " TX_REL");
@ -545,9 +555,8 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType)
else fprintf(stderr, " Unknown M-%02X", MessageType);
fprintf (stderr, "%s", KNRM);
//zero out stale values so they won't persist after a transmit release
//disable if random messages wipe out the alias
if (MessageType == 0x08 || MessageType == 0x10) //idle, tx_rel
//zero out stale values so they won't persist after a transmit release, idle, or disconnect
if (MessageType == 0x08 || MessageType == 0x10 || MessageType == 0x11) //tx_rel, idle, or disc
{
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
state->nxdn_last_rid = 0;

View File

@ -18,7 +18,7 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
uint32_t i;
uint8_t CrcCorrect = 1;
/* Consider all SACCH CRC parts as corrects */
/* Consider all SACCH CRC parts as correct */
CrcCorrect = 1;
/* Reconstitute the full 72 bits SACCH */
@ -33,6 +33,7 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state)
/* Decodes the element content */
// currently only going to run this if all four CRCs are good
if (CrcCorrect == 1) NXDN_Elements_Content_decode(opts, state, CrcCorrect, SACCH);
else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, SACCH);
} /* End NXDN_SACCH_Full_decode() */
@ -272,13 +273,9 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
if (opts->p25_trunk == 1 && state->p25_cc_freq == 0)
{
long int ccfreq = 0;
if (state->trunk_chan_map[0] != 0) state->p25_cc_freq = state->trunk_chan_map[0];
//we are assuming that the current channel is the control channel
//unsure whether or not control signalling is available on NXDN voice channels
//if not available from the import file, then poll rigctl if its available
else if (opts->use_rigctl == 1)
//if not available, then poll rigctl if its available
if (opts->use_rigctl == 1)
{
ccfreq = GetCurrentFreq (opts->rigctl_sockfd);
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
@ -291,6 +288,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
}
}
//run group/source analysis and tune if available/desired
//group list mode so we can look and see if we need to block tuning any groups, etc
char mode[8]; //allow, block, digital, enc, etc
@ -459,31 +457,9 @@ void NXDN_decode_cch_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
freq1 = nxdn_channel_to_frequency (opts, state, channel1);
freq2 = nxdn_channel_to_frequency (opts, state, channel2);
//add handling for adding (or deleting?) frequencies to CC list
if (channel1sts & 0x20 || channel1sts & 0x8) //current or new only
{
if (freq1 != 0) state->p25_cc_freq = freq1;
//let's assume the frequency we are tuned to is the current control channel
else if (opts->use_rigctl == 1 && state->p25_cc_freq == 0) //if not set from channel map 0 or nxdn_channel_to_frequency and rigctl is available
{
freq1 = GetCurrentFreq (opts->rigctl_sockfd);
if (freq1 != 0) state->p25_cc_freq = freq1;
}
}
else if (channel1sts & 0x8) //Candidate Added
{
if (freq1 != 0)
{
//add to trunk_lcn_freq list?
for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep
{
if (freq1 == state->trunk_lcn_freq[i]) goto SKIP;
}
//assign if freq1 not found in array
state->trunk_lcn_freq[state->lcn_freq_count] = freq1;
state->lcn_freq_count++;
}
}
//removed code below, may have been causing issues with current CC frequency assignment
//removed code is unneccesary for trunking purposes
//if a delete, let's not bother trying to remove it from the list for now
SKIP: ; //do nothing
@ -507,6 +483,25 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
nxdn_location_id_handler (state, location_id);
fprintf (stderr, "%s", KNRM);
//poll for current frequency, will always be the control channel
//this PDU is constantly pumped out on the CC CAC Message
if (opts->p25_trunk == 1)
{
long int ccfreq = 0;
//if using rigctl, we can poll for the current frequency
if (opts->use_rigctl == 1)
{
ccfreq = GetCurrentFreq (opts->rigctl_sockfd);
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
}
//if using rtl input, we can ask for the current frequency tuned
else if (opts->audio_in_type == 3)
{
ccfreq = (long int)opts->rtlsdr_center_freq;
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
}
}
}
//externalize the location handler to its own function
@ -596,31 +591,9 @@ void NXDN_decode_site_info(dsd_opts * opts, dsd_state * state, uint8_t * Message
fprintf (stderr, "%s", KNRM);
//place the freqs into the array for hunting CC or
//rotating CCs without user LCN list
if (freq1 != 0)
{
for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep
{
if (freq1 == state->trunk_lcn_freq[i]) goto SKIP;
}
//assign if freq1 not found in array
state->trunk_lcn_freq[state->lcn_freq_count] = freq1;
state->lcn_freq_count++;
//shim here for main CC freq?
state->p25_cc_freq = freq1;
}
//removed code below, may have been causing issues with current CC frequency assignment
//removed code is unneccesary for trunking purposes
if (freq2 != 0)
{
for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep
{
if (freq2 == state->trunk_lcn_freq[i]) goto SKIP;
}
//assign if freq2 not found in array
state->trunk_lcn_freq[state->lcn_freq_count] = freq2;
state->lcn_freq_count++;
}
SKIP: ; //do nothing
@ -703,11 +676,19 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID];
else if (state->rkey_array[DestinationID] != 0) state->R = state->rkey_array[DestinationID];
if (state->M == 1)
{
state->nxdn_cipher_type = 0x1;
CipherType = 0x1;
}
//consider removing code below, if we get this far (under good crc),
//then we will always have a correct cipher type and won't need to
//force it, its only needed on the vcall_assgn where no cipher is set
//dsd_mbe can also force the scrambler without triggering the settings here
// if (state->M == 1)
// {
// state->nxdn_cipher_type = 0x1;
// CipherType = 0x1;
// }
//debug
// if (CipherType > 0x1) state->R = 0; //don't use on manual key entry
/* Print the "Cipher Type" */
if(CipherType != 0)

View File

@ -45,40 +45,48 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
int sr_structure;
int sr_ran;
uint8_t lich_dibits[8] = {0};
uint8_t sacch_bits[60] = {0};
uint8_t facch_bits_a[144] = {0};
uint8_t facch_bits_b[144] = {0};
uint8_t cac_bits[300] = {0};
uint8_t facch2_bits[348] = {0}; //facch2 or udch, same amount of bits
uint8_t lich_dibits[8];
uint8_t sacch_bits[60];
uint8_t facch_bits_a[144];
uint8_t facch_bits_b[144];
uint8_t cac_bits[300];
uint8_t facch2_bits[348]; //facch2 or udch, same amount of bits
//nxdn bit buffer, for easy assignment handling
int nxdn_bit_buffer[364] = {0};
int nxdn_dibit_buffer[182] = {0};
int nxdn_bit_buffer[364];
int nxdn_dibit_buffer[182];
//init all arrays
memset (dbuf, 0, sizeof(dbuf));
memset (answer, 0, sizeof(answer));
memset (sacch_answer, 0, sizeof(sacch_answer));
memset (lich_dibits, 0, sizeof(lich_dibits));
memset (sacch_bits, 0, sizeof(sacch_bits));
memset (facch_bits_b, 0, sizeof(facch_bits_b));
memset (facch_bits_a, 0, sizeof(facch_bits_a));
memset (cac_bits, 0, sizeof(cac_bits));
memset (facch2_bits, 0, sizeof(facch2_bits));
memset (nxdn_bit_buffer, 0, sizeof(nxdn_bit_buffer));
memset (nxdn_dibit_buffer, 0, sizeof(nxdn_dibit_buffer));
//collect lich bits first, if they are good, then we can collect the rest of them
for (int i = 0; i < 8; i++)
{
lich_dibits[i] = dbuf[i] = getDibit(opts, state);
}
for (int i = 0; i < 8; i++) lich_dibits[i] = dbuf[i] = getDibit(opts, state);
nxdn_descramble (lich_dibits, 8);
lich = 0;
for (int i=0; i<8; i++)
{
lich |= (lich_dibits[i] >> 1) << (7-i);
}
for (int i=0; i<8; i++) lich |= (lich_dibits[i] >> 1) << (7-i);
lich_parity_received = lich & 1;
lich_parity_computed = ((lich >> 7) + (lich >> 6) + (lich >> 5) + (lich >> 4)) & 1;
lich = lich >> 1;
if (lich_parity_received != lich_parity_computed)
{
//fprintf(stderr, "NXDN lich parity error, ignoring frame \n");
return;
// fprintf(stderr, "NXDN lich parity error, ignoring frame \n"); //debug
// state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly
goto END;
// return;
}
voice = 0;
@ -92,6 +100,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
if (lich % 2 == 0 && opts->p25_trunk == 1)
{
if (opts->payload == 1) fprintf(stderr, " Simplex/Inbound NXDN lich on trunking system - type 0x%02X\n", lich);
// state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly
goto END;
}
@ -225,12 +234,18 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
//vch frames stay inside dbuf, easier to assign that to ambe_fr frames
//sacch needs extra handling depending on superframe or non-superframe variety
if (voice)
if (voice && !facch) //voice only, no facch steal
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Voice ");
fprintf (stderr, "%s", KNRM);
}
else if (voice && facch) //voice with facch steal
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " V%d+F%d ", 3 - facch, facch); //print which position on each
fprintf (stderr, "%s", KNRM);
}
else
{
fprintf (stderr, "%s", KCYN);
@ -238,7 +253,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM);
//roll the voice scrambler LFSR here if key available to advance seed (usually just needed on NXDN96)
if (state->nxdn_cipher_type == 0x1 && state->R != 0) //!voice, or voice == 0
if (state->nxdn_cipher_type == 0x1 && state->R != 0)
{
char ambe_temp[49] = {0};
char ambe_d[49] = {0};
@ -248,16 +263,38 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
}
}
}
}
if (voice && facch == 1) //facch steal 1 -- before voice
{
//force scrambler here, but with unspecified key (just use what's loaded)
if (state->M == 1 && state->R != 0) state->nxdn_cipher_type = 0x1;
//roll the voice scrambler LFSR here if key available to advance seed -- half rotation on a facch steal
if (state->nxdn_cipher_type == 0x1 && state->R != 0)
{
char ambe_temp[49] = {0};
char ambe_d[49] = {0};
for (int i = 0; i < 2; i++)
{
LFSRN(ambe_temp, ambe_d, state);
}
}
}
if (lich == 0x20 || lich == 0x21 || lich == 0x61 || lich == 0x40 || lich == 0x41) state->nxdn_sacch_non_superframe = TRUE;
else state->nxdn_sacch_non_superframe = FALSE;
if (sacch)nxdn_deperm_sacch(opts, state, sacch_bits);
if (cac) nxdn_deperm_cac(opts, state, cac_bits);
if (sacch) nxdn_deperm_sacch(opts, state, sacch_bits);
if (cac) nxdn_deperm_cac(opts, state, cac_bits);
if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits);
if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
//testing purposes -- don't run facch steals on enc -- causing issues with key loader (VCALL_ASSGN_DUP)
if (state->nxdn_cipher_type == 0 || state->R == 0) //!voice
{
if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a);
if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b);
}
if (voice)
{
//restore MBE file open here
@ -281,7 +318,22 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
}
if (opts->frame_nxdn48 == 1) closeMbeOutFile (opts, state); //okay to close right away if nxdn48, no data/voice mixing
}
}
}
if (voice && facch == 2) //facch steal 2 -- after voice
{
//roll the voice scrambler LFSR here if key available to advance seed -- half rotation on a facch steal
if (state->nxdn_cipher_type == 0x1 && state->R != 0)
{
char ambe_temp[49] = {0};
char ambe_d[49] = {0};
for (int i = 0; i < 2; i++)
{
LFSRN(ambe_temp, ambe_d, state);
}
}
}
fprintf (stderr, "\n");
END: ; //do nothing