diff --git a/include/dsd.h b/include/dsd.h index 7ad75b5..6b12078 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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]; diff --git a/src/dsd_main.c b/src/dsd_main.c index ef5dedf..575b205 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -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 diff --git a/src/nxdn_deperm.c b/src/nxdn_deperm.c index 221db3d..8b4f104 100644 --- a/src/nxdn_deperm.c +++ b/src/nxdn_deperm.c @@ -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;iuse_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); diff --git a/src/nxdn_frame.c b/src/nxdn_frame.c index 4086954..157550a 100644 --- a/src/nxdn_frame.c +++ b/src/nxdn_frame.c @@ -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);