NXDN Tweaks and SACCH/FACCH CRC Fixes;
This commit is contained in:
parent
a3b8839897
commit
c4513fab7a
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue