NXDN Tweaks and SACCH/FACCH CRC Fixes;

This commit is contained in:
lwvmobile 2023-02-22 19:46:06 -05:00
parent a3b8839897
commit c4513fab7a
5 changed files with 69 additions and 55 deletions

View File

@ -657,7 +657,7 @@ typedef struct
uint16_t nxdn_location_site_code;
//multi-key array for nxdn keys
unsigned long long int rkey_array[0x1FF];
unsigned long long int rkey_array[0xFFFF];
//dmr late entry mi
uint64_t late_entry_mi_fragment[2][7][3];

View File

@ -288,7 +288,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->nxdn_sf = 0;
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); //init on 1, bad CRC all
state->nxdn_sacch_non_superframe = TRUE;
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
state->nxdn_alias_block_number = 0;
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
sprintf (state->nxdn_call_type, "%s", "");
@ -815,7 +815,7 @@ initState (dsd_state * state)
state->nxdn_sf = 0;
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc)); //init on 1, bad CRC all
state->nxdn_sacch_non_superframe = TRUE;
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
state->nxdn_alias_block_number = 0;
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
//site/srv/cch info

View File

@ -111,17 +111,15 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
}
//load tail 16 bits into check variable to compare vs computed crc value
crc = crc12f (trellis_buf, 84); //80
for (int i = 0; i < 12; i++)
{
check = check << 1;
check = check + trellis_buf[80+i];
check = check | trellis_buf[84+i]; //80
}
crc = crc12f (trellis_buf, 80);
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->payload == 1) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
if (opts->payload == 1)
{
@ -131,7 +129,7 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
{
fprintf (stderr, "[%02X]", m_data[i]);
}
fprintf (stderr, " - %03X %03X", crc, check);
fprintf (stderr, " - %03X %03X", check, crc);
}
}
@ -211,11 +209,11 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
}
crc = crc6(trellis_buf, 32);
crc = crc6(trellis_buf, 26); //32
for (int i = 0; i < 6; i++)
{
check = check << 1;
check = check + trellis_buf[i+26];
check = check | trellis_buf[i+26];
}
//FIRST! If part of a non_superframe, and CRC is good, send directly to NXDN_Elements_Content_decode
@ -231,16 +229,16 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
nsf_sacch[i] = trellis_buf[i+8];
}
if (crc == 0) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch);
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch);
if (opts->payload == 1)
{
fprintf (stderr, "\n SACCH NSF ");
for (int i = 0; i < 5; i++)
for (int i = 0; i < 4; i++)
{
fprintf (stderr, "[%02X]", m_data[i]);
}
if (crc != 0) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", check, crc);
}
}
@ -266,7 +264,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
//reset scrambler seed to key value on new superframe
if (part_of_frame == 0 && state->nxdn_cipher_type == 0x1) state->payload_miN = 0;
if (crc == 0)
if (crc == check)
{
state->nxdn_ran = state->nxdn_last_ran = ran;
state->nxdn_sf = sf;
@ -294,11 +292,11 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
{
fprintf (stderr, "\n");
fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
for (int i = 0; i < 5; i++)
for (int i = 0; i < 4; i++)
{
fprintf (stderr, "[%02X]", m_data[i]);
}
if (crc != 0) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
}
}
@ -312,6 +310,7 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
uint8_t trellis_buf[199];
int id = 0;
uint16_t crc = 0;
uint16_t check = 0;
for (int i=0; i<348; i++) {
deperm[PERM_12_29[i]] = bits[i];
@ -377,6 +376,11 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
}
crc = crc15(trellis_buf, 199);
for (int i = 0; i < 15; i++)
{
check = check << 1;
check = check | trellis_buf[i+184];
}
uint8_t f2u_message_buffer[199];
memset (f2u_message_buffer, 0, sizeof(f2u_message_buffer));
@ -388,7 +392,7 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
f2u_message_buffer[i] = trellis_buf[i+8];
}
if (crc == 0)
if (crc == check)
{
fprintf (stderr, " F2/U ");
//NXDN_Elements_Content_decode(opts, state, 1, trellis_buf);
@ -404,7 +408,7 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34
fprintf (stderr, "[%02X]", m_data[i]);
if (i == 12) fprintf (stderr, "\n ");
}
if (crc != 0) fprintf (stderr, " CRC ERR ");
if (crc != check) fprintf (stderr, " CRC ERR ");
}
}
@ -452,11 +456,6 @@ void nxdn_deperm_cac(dsd_opts * opts, dsd_state * state, uint8_t bits[300])
temp[i] = depunc[i] << 1;
}
for (int i = 0; i < 8; i++)
{
temp[i+350] = 0;
}
CNXDNConvolution_start();
for (int i = 0U; i < 179U; i++)
{
@ -482,20 +481,11 @@ void nxdn_deperm_cac(dsd_opts * opts, dsd_state * state, uint8_t bits[300])
crc = crc16cac(trellis_buf, 171);
//message type will probably be neccesary beforehand on single/dual meessage runs
//run message, check len, load into a seperate buffer, send to element, do same with other piece?
uint8_t MessageType = 0;
for (int i = 0; i < 6; i++)
{
MessageType = MessageType << 1;
MessageType = MessageType + trellis_buf[i+2]; //double check this on CAC
}
uint8_t cac_message_buffer[171];
memset (cac_message_buffer, 0, sizeof(cac_message_buffer));
//shift the cac_message into the appropriate byte arrangement for element_decoder
for (int i = 0; i < 160; i++) //in future, we can use this to send multiple messages to decoder, if present
//shift the cac_message into the appropriate byte arrangement for element_decoder -- skip SR field
for (int i = 0; i < 160; i++)
{
cac_message_buffer[i] = trellis_buf[i+8];
}
@ -564,7 +554,7 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType)
state->nxdn_last_tg = 0;
state->nxdn_cipher_type = 0;
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
sprintf (state->nxdn_call_type, "%s", "");
}
}
@ -669,13 +659,13 @@ static uint16_t crc15(const uint8_t buf[], int len)
static uint16_t crc16cac(const uint8_t buf[], int len)
{
int crc = 0xc3ee;
int poly = (1<<12) + (1<<5) + 1;
for (int i=0;i<len;i++) {
crc = ((crc << 1) | buf[i]) & 0x1ffff;
if(crc & 0x10000)
crc = (crc & 0xffff) ^ poly;
uint32_t crc = 0xc3ee; //not sure why this though
uint32_t poly = (1<<12) + (1<<5) + 1; //poly is fine
for (int i=0;i<len;i++)
{
crc = ((crc << 1) | buf[i]) & 0x1ffff;
if(crc & 0x10000) crc = (crc & 0xffff) ^ poly;
}
crc = crc ^ 0xffff;
return crc & 0xffff;
crc = crc ^ 0xffff;
return crc & 0xffff;
}

View File

@ -288,35 +288,44 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
if (opts->use_rigctl == 1)
{
//extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
state->lastsynctype = -1;
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL); //useful?
//
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
//set rid and tg when we actually tune to it
state->nxdn_last_rid = SourceUnitID & 0xFFFF;
state->nxdn_last_tg = (DestinationID & 0xFFFF);
sprintf (state->nxdn_call_type, "%s", NXDN_Call_Type_To_Str(CallType));
}
//rtl_udp
else if (opts->audio_in_type == 3)
{
//extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
state->lastsynctype = -1;
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL);
//
rtl_udp_tune (opts, state, freq);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
opts->p25_is_tuned = 1;
//set rid and tg when we actually tune to it
state->nxdn_last_rid = SourceUnitID & 0xFFFF;
state->nxdn_last_tg = (DestinationID & 0xFFFF);
sprintf (state->nxdn_call_type, "%s", NXDN_Call_Type_To_Str(CallType));
}
//set rid and tg when we actually tune to it
state->nxdn_last_rid = SourceUnitID & 0xFFFF;
state->nxdn_last_tg = (DestinationID & 0xFFFF);
sprintf (state->nxdn_call_type, "%s", NXDN_Call_Type_To_Str(CallType));
}
}
@ -668,7 +677,11 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
}
//check the rkey array for a scrambler key value
//check by keyid first, then by tgt id
//TGT ID and Key ID could clash though if csv or system has both
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];
else state->R = 0;
if (state->nxdn_cipher_type == 0x01 && state->R > 0) //scrambler key value
{
@ -680,7 +693,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message)
//only grab if CRC is okay
if(state->NxdnElementsContent.VCallCrcIsGood)
{
if ( (SourceUnitID & 0xFFFF) > 0 )
if ( (SourceUnitID & 0xFFFF) > 0 ) //
{
state->nxdn_last_rid = SourceUnitID & 0xFFFF;
state->nxdn_last_tg = (DestinationID & 0xFFFF);

View File

@ -86,6 +86,15 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
facch2 = 0;
sacch = 0;
cac = 0;
//test for inbound direction lich when trunking (false positive) and skip
//all inbound lich are even value (lsb is set to 0 for inbound direction)
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);
goto END;
}
switch(lich) { //cases without breaks continue to flow downwards until they hit the break
case 0x01: // CAC types
case 0x05:
@ -123,7 +132,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
break;
case 0x36: //vch in both
case 0x37:
case 0x56:
case 0x56:
case 0x57:
case 0x77:
voice = 3;
@ -151,7 +160,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
default:
if (opts->payload == 1) fprintf(stderr, " false sync or unsupported NXDN lich type 0x%02X\n", lich);
//reset the sacch field, we probably got a false sync and need to wipe or give a bad crc
memset (state->nxdn_sacch_frame_segment, 0, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly
voice = 0;
@ -241,7 +250,9 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
}
state->nxdn_sacch_non_superframe = (lich == 0x20 || lich == 0x21 || lich == 0x61 || lich == 0x40 || lich == 0x41) ? true : false;
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 (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits);