diff --git a/include/dsd.h b/include/dsd.h index db140dd..37f29fe 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -535,7 +535,7 @@ typedef struct uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte] uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data - char dmr_embedded_signalling[2][6][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure) + char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure) char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet. @@ -879,7 +879,7 @@ int32_t GetdPmrColorCode(uint8_t ChannelCodeBit[24]); void BPTCDeInterleaveDMRData(uint8_t * Input, uint8_t * Output); uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DMRDataExtracted[96], uint8_t R[3]); uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDataExtracted[77]); -uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32]); +uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32], uint32_t ParityCheckTypeOdd); //Reed Solomon (12,9) functions void rs_12_9_calc_syndrome(rs_12_9_codeword_t *codeword, rs_12_9_poly_t *syndrome); @@ -892,6 +892,8 @@ uint16_t ComputeCrcCCITT(uint8_t * DMRData); uint16_t ComputeCrcCCITT16d(const uint8_t buf[], uint8_t len); uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes, uint32_t * CRCComputed, uint32_t CRCMask); uint8_t ComputeCrc5Bit(uint8_t * DMRData); +uint16_t ComputeCrc9Bit(uint8_t * DMRData, uint32_t NbData); +uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData); //new simplified dmr functions void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t databurst); @@ -927,10 +929,14 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state); void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc, char ambe_fr[4][24], char ambe_fr2[4][24], char ambe_fr3[4][24]); void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state); +//handle Single Burst (Voice Burst F) or Reverse Channel Signalling +void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power); + //DMR FEC/CRC from Boatbod - OP25 bool Hamming17123(uint8_t* d); uint8_t crc8(uint8_t bits[], unsigned int len); bool crc8_ok(uint8_t bits[], unsigned int len); +uint8_t crc7(uint8_t bits[], unsigned int len); //LFSR code courtesy of https://github.com/mattames/LFSR/ void LFSR(dsd_state * state); diff --git a/src/bptc.c b/src/bptc.c index 7f6ddff..74ac0e2 100644 --- a/src/bptc.c +++ b/src/bptc.c @@ -134,6 +134,13 @@ const uint8_t DeInterleaveReverseChannelBptc[32] = 24, 9, 26, 11, 28, 13, 30, 15 }; +const uint8_t DeInterleaveReverseChannelBptcPlacement[32] = +{ + 0, 16, 1, 17, 2, 18, 3, 19, + 4, 20, 5, 21, 6, 22, 7, 23, + 8, 24, 9, 25, 10, 26, 11, 27, + 12, 28, 13, 29, 14, 30, 15, 31 +}; /* Functions ----------------------------------------------------------------*/ @@ -498,33 +505,38 @@ uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDat * DMRDataExtracted[11..15] = Hamming data * DMRDataExtracted[16..31] = 16 bits of odd parity (to be checked) * + * @param ParityCheckTypeOdd : 0 = Parity to check is even (used in Non-Reverse Channel Single Burst BPTC) + * 1 = Parity to check is odd (used in Reverse Channel Single Burst BPTC) + * * @return 0 = All is OK * Other = Error - Irrecoverable Hamming parity check error number */ -uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32]) +uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32], uint32_t ParityCheckTypeOdd) { uint32_t i; uint8_t DataMatrix[32]; uint8_t LineUncorrected[16]; uint8_t LineCorrected[11]; uint32_t HammingIrrecoverableErrorNb = 0; - uint32_t ParityCheckErrorNb = 0; + uint32_t ParityCheckOddErrorNb = 0; + uint32_t ParityCheckEvenErrorNb = 0; + //TODO: make this so we can load either rc interleave, or single burst interleave for(i = 0; i < 32; i++) { - DataMatrix[DeInterleaveReverseChannelBptc[i]] = InputInterleavedData[i] & 1; + DataMatrix[DeInterleaveReverseChannelBptcPlacement[DeInterleaveReverseChannelBptc[i]]] = InputInterleavedData[i] & 1; } /* Copy the entire input buffer to the output buffer */ for(i = 0; i < 32; i++) { - DMRDataExtracted[i] = DataMatrix[i]; + DMRDataExtracted[i] = DataMatrix[i] & 1; } /* Prepare the line to be corrected */ for(i = 0; i < 16; i++) { - LineUncorrected[i] = DataMatrix[i]; + LineUncorrected[i] = DataMatrix[i] & 1; } /* Apply Hamming (16,11,4) code correction */ @@ -536,7 +548,7 @@ uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDat /* Copy the corrected content to the output buffer */ for(i = 0; i < 11; i++) { - DMRDataExtracted[i] = LineCorrected[i]; + DMRDataExtracted[i] = LineCorrected[i] & 1; } /* Check Parity bits */ @@ -544,14 +556,24 @@ uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDat { /* Odd parity ==> If data = 1 then parity = 0 * If data = 0 then parity = 1 */ - if(DMRDataExtracted[i] == DMRDataExtracted[i + 16]) ParityCheckErrorNb++; + if((DMRDataExtracted[i] & 1) == (DMRDataExtracted[i + 16] & 1)) ParityCheckOddErrorNb++; + if((DMRDataExtracted[i] & 1) != (DMRDataExtracted[i + 16] & 1)) ParityCheckEvenErrorNb++; } - //fprintf(stderr, "Hamming ERR=%u ; Parity ERR=%u", HammingIrrecoverableErrorNb, ParityCheckErrorNb); + //fprintf(stderr, "Hamming ERR=%u ; Parity odd ERR=%u, Parity even ERR=%u, ", HammingIrrecoverableErrorNb, ParityCheckOddErrorNb, ParityCheckEvenErrorNb); + + //fprintf(stderr, "Content =\n"); + //for(i = 0; i < 32; i++) + //{ + // fprintf(stderr, "%u", DMRDataExtracted[i] & 1); + // if((i == 15) || (i == 31)) fprintf(stderr, "\n"); + // else fprintf(stderr, "-"); + //} /* Return the number of irrecoverable Hamming errors + * the number of parity check error */ - return (HammingIrrecoverableErrorNb + ParityCheckErrorNb); + if(ParityCheckTypeOdd) return (HammingIrrecoverableErrorNb + ParityCheckOddErrorNb); + else return (HammingIrrecoverableErrorNb + ParityCheckEvenErrorNb); } /* End BPTC_16x2_Extract_Data() */ diff --git a/src/dmr_bs.c b/src/dmr_bs.c index a319bb2..831a0ab 100644 --- a/src/dmr_bs.c +++ b/src/dmr_bs.c @@ -41,6 +41,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state) uint8_t internalslot; uint8_t vc1; uint8_t vc2; + + //assign as nonsensical numbers + uint8_t cc = 25; + uint8_t power = 9; //power and pre-emption indicator + uint8_t lcss = 9; //would be ideal to grab all dibits and break them into bits to pass to new data handler? uint8_t dummy_bits[196]; @@ -189,13 +194,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state) syncdata[(2*i)+1] = (1 & dibit); // bit 0 //embedded link control - if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E + if(internalslot == 0 && vc1 > 1 && vc1 < 7) //grab on vc1 values 2-5 B C D and E { state->dmr_embedded_signalling[internalslot][vc1-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc1-1][i*2+1] = (1 & dibit); // bit 0 } - if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E + if(internalslot == 1 && vc2 > 1 && vc2 < 7) //grab on vc2 values 2-5 B C D and E { state->dmr_embedded_signalling[internalslot][vc2-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc2-1][i*2+1] = (1 & dibit); // bit 0 @@ -300,9 +305,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state) if ( (strcmp (sync, DMR_BS_VOICE_SYNC) != 0) && emb_ok == 0) goto END; //fprintf (stderr, "EMB BAD? "); else if (emb_ok == 1) { - uint8_t cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); - uint8_t power = EmbeddedSignalling[4]; - uint8_t lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); + cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + power = EmbeddedSignalling[4]; + lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); } @@ -339,6 +344,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state) //process embedded link control fprintf (stderr, "\n"); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); + //check the single burst/reverse channel opportunity + dmr_sbrc (opts, state, power); } if (internalslot == 1 && vc2 == 6) @@ -346,6 +353,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state) //process embedded link control fprintf (stderr, "\n"); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); + //check the single burst/reverse channel opportunity + dmr_sbrc (opts, state, power); } if (opts->payload == 1) fprintf (stderr, "\n"); //extra line break necessary here @@ -418,6 +427,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state) cach_err = 1; tact_okay = 0; emb_ok = 0; + + //reset emb components + cc = 25; + power = 9; + lcss = 9; //Extra safeguards to break loop // if ( (vc1 > 7 && vc2 > 7) ) goto END; diff --git a/src/dmr_dburst.c b/src/dmr_dburst.c index 0092ea9..374aac5 100644 --- a/src/dmr_dburst.c +++ b/src/dmr_dburst.c @@ -45,9 +45,10 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 uint8_t R[3]; uint8_t BPTCReservedBits = 0; + uint8_t is_ras = 0; uint32_t crcmask = 0; - uint8_t crclen = 0; + uint8_t crclen = 0; uint8_t is_bptc = 0; uint8_t is_trellis = 0; @@ -204,7 +205,13 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 IrrecoverableErrors = BPTC_196x96_Extract_Data(BPTCDeInteleavedData, BPTCDmrDataBit, R); /* Fill the reserved bit (R(0)-R(2) of the BPTC(196,96) block) */ - BPTCReservedBits = (R[0] & 0x01) | ((R[1] << 1) & 0x02) | ((R[2] << 2) & 0x08); + BPTCReservedBits = (R[0] & 0x01) | ((R[1] << 1) & 0x02) | ((R[2] << 2) & 0x04); + + //debug print + //fprintf (stderr, " RAS? %X - %d %d %d", BPTCReservedBits, R[0], R[1], R[2]); + + //set the 'RAS Flag' + if (BPTCReservedBits != 0) is_ras = 1; //!=0, or == 0x4 /* Convert the 96 bits BPTC data into 12 bytes */ k = 0; @@ -436,6 +443,15 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 } if (databurst == 0x05) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 2); + //print whether or not the 'RAS Field' bits are set to indicate RAS enabled (to be verified) + if (IrrecoverableErrors == 0 && is_ras == 1) + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, " RAS "); + if (opts->payload == 1) fprintf (stderr, "%X ", BPTCReservedBits); + fprintf (stderr, "%s", KNRM); + } + //print the unified PDU format here, if not slot idle if (opts->payload == 1 && databurst != 0x09) { diff --git a/src/dmr_flco.c b/src/dmr_flco.c index c263592..22f7ba9 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -133,6 +133,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C // state->lastsrc = 0; state->payload_algid = 0; state->payload_mi = 0; + state->payload_keyid = 0; } if (state->currentslot == 1) { @@ -142,6 +143,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C // state->lastsrcR = 0; state->payload_algidR = 0; state->payload_miR = 0; + state->payload_keyidR = 0; } } @@ -164,14 +166,32 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C fprintf(stderr, "TGT=%u SRC=%u ", target, source); if (opts->payload == 1) fprintf(stderr, "FLCO=0x%02X FID=0x%02X SVC=0x%02X ", flco, fid, so); - if (flco == 0x3 || flco == 0x7 || flco == 0x23) //UU_V_Ch_Usr, Cap+ Private TXI call (VLC), or Cap+ Private TXI call (EMB) + //0x04 and 0x05 on a TLC seem to indicate a Cap + Private Call Terminator (perhaps one for each MS) + //0x07 on a VLC seems to indicate a Cap+ Private Call Header + //0x23 on the Embedded Voice Burst Sync seems to indicate a Cap+ Private Call in progress + if (flco == 0x4 || flco == 0x5 || flco == 0x7 || flco == 0x23) //Cap+ Things { - sprintf (state->call_string[slot], " Private"); + sprintf (state->call_string[slot], " Cap+"); + fprintf (stderr, "Cap+ "); + if (flco == 0x4) + { + strcat (state->call_string[slot], " Grp"); + fprintf (stderr, "Group "); + } + else + { + strcat (state->call_string[slot], " Pri"); + fprintf (stderr, "Private "); + } + } + else if (flco == 0x3) //UU_V_Ch_Usr + { + sprintf (state->call_string[slot], " Private "); fprintf (stderr, "Private "); - } + } else //Grp_V_Ch_Usr { - sprintf (state->call_string[slot], " Group"); + sprintf (state->call_string[slot], " Group "); fprintf (stderr, "Group "); } @@ -208,7 +228,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C { //REMUS! Uncomment Line Below if desired // strcat (state->call_string[slot], " RES"); - fprintf(stderr, "Reserved=%d ", (so & 0x30) >> 4); + fprintf(stderr, "RS%d ", (so & 0x30) >> 4); } } if(so & 0x08) @@ -255,8 +275,8 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C fprintf (stderr, "%s", KRED); if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good - else if(IrrecoverableErrors == 0) fprintf(stderr, "(FEC/RAS)"); - else fprintf(stderr, "(FEC/CRC ERR)"); + else if(IrrecoverableErrors == 0) ; //fprintf(stderr, "(FEC OK)"); + else fprintf(stderr, "(FEC/CRC ERR) "); //check Cap+ rest channel info if available and good fec if (is_cap_plus == 1) diff --git a/src/dmr_le.c b/src/dmr_le.c index 646f92d..f247d3f 100644 --- a/src/dmr_le.c +++ b/src/dmr_le.c @@ -137,3 +137,151 @@ void dmr_alg_reset (dsd_opts * opts, dsd_state * state) state->payload_miP = 0; } +//handle Single Burst (Voice Burst F) or Reverse Channel Signalling +//(Embedded or Dedicated Outbound, not Stand Alone (MS sourced) or Direct Mode) +//MS Sourced or Direct Mode probably would be handled poorly by the demodulator +void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power) +{ + int i; + uint8_t slot = state->currentslot; + uint8_t sbrc_interleaved[32]; + uint8_t sbrc_return[32]; + memset (sbrc_interleaved, 0, sizeof(sbrc_interleaved)); + memset (sbrc_return, 0, sizeof(sbrc_return)); + uint32_t irr_err = 0; + uint32_t sbrc_hex = 0; + uint16_t crc_extracted = 7777; + uint16_t crc_computed = 9999; + uint8_t crc_okay = 0; + + // 9.3.2 Pre-emption and power control Indicator (PI) + // 0 - The embedded signalling carries information associated to the same logical channel or the Null embedded message + // 1 - The embedded signalling carries RC information associated to the other logical channel + + for(i = 0; i < 32; i++) sbrc_interleaved[i] = state->dmr_embedded_signalling[slot][5][i + 8]; + //power == 0 should be single burst + if (power == 0) irr_err = BPTC_16x2_Extract_Data(sbrc_interleaved, sbrc_return, 0); + //power == 1 should be reverse channel -- still need to check the interleave inside of BPTC + if (power == 1) irr_err = BPTC_16x2_Extract_Data(sbrc_interleaved, sbrc_return, 1); + //bad emb burst, never set a valid power indicator value (probably 9) + if (power > 1) goto SBRC_END; + + //RC Channel CRC 7 Mask = 0x7A; CRC bits are used as privacy indicators on + //Single Voice Burst F (see below), other moto values seem to exist there as well + //unknown what the other values are (see Cap+ 0x313) + if (power == 1) //RC + { + crc_extracted = 0; + for (i = 0; i < 7; i++) + { + crc_extracted = crc_extracted << 1; + crc_extracted = crc_extracted | sbrc_return[i+4]; + } + crc_extracted = crc_extracted ^ 0x7A; + crc_computed = crc7((uint8_t *) sbrc_return, 11); + if (crc_extracted == crc_computed) crc_okay = 1; + if (opts->payload == 1) fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed); + } + else crc_okay = 1; //SB + + fprintf (stderr, "\n %s", KCYN); + if (power == 0) fprintf (stderr, " SB: "); + if (power == 1) fprintf (stderr, " RC: "); + for(i = 0; i < 11; i++) + { + sbrc_hex = sbrc_hex << 1; + sbrc_hex |= sbrc_return[i] & 1; //sbrc_return + fprintf (stderr, "%d", sbrc_return[i]); + } + fprintf (stderr, " - %03X", sbrc_hex); + fprintf (stderr, "%s", KNRM); + + if (crc_okay == 0) + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, " (CRC ERR)"); + fprintf (stderr, "%s", KNRM); + } + + //sbrc_hex value of 0x313 seems to be some Cap+ Thing, + //also observed 0x643 on another cap+ system (site id, status? something?) + //I've observed it in the Private Cap+ TXI calls as well + //there also seems to be a correlation between the SVC bits for TXI (reserved=3) and these extra cap+ values + uint8_t sbrc_opcode = sbrc_hex; + uint8_t alg = sbrc_hex & 3; + uint16_t key = (sbrc_hex >> 3) & 0xFF; + + if (irr_err != 0) fprintf (stderr, "%s (FEC ERR) %d %s", KRED, irr_err, KNRM); + if (irr_err == 0) + { + if (sbrc_hex == 0) ; //NULL + else if (sbrc_hex == 0x313) + { + //Cap+ Thing? Observed On Cap+ Systems + // fprintf (stderr, " Cap+ Thing?"); + } + else + { + + if (slot == 0) + { + //key and alg only present SOME times, not all, + //also, intermixed with other signalling + //needs more study first! + if (state->dmr_so & 0x40 && key != 0 && state->payload_keyid == 0) + { + if (opts->payload == 1) + { + fprintf (stderr, "%s ", KYEL); + fprintf (stderr, "\n Slot 1"); + fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key); + fprintf (stderr, "%s ", KNRM); + } + + //needs more study before assignment + //state->payload_keyid = key; + //state->payload_algid = alg + 0x20; //assuming DMRA approved alg values (moto patent) + } + } + if (slot == 1) + { + if (state->dmr_soR & 0x40 && key != 0 && state->payload_keyidR == 0) + { + if (opts->payload == 1) + { + fprintf (stderr, "%s ", KYEL); + fprintf (stderr, "\n Slot 2"); + fprintf (stderr, " DMR LE SB ALG ID: %X KEY ID: %0X", alg + 0x20, key); + fprintf (stderr, "%s ", KNRM); + } + + //needs more study before assignment + //state->payload_keyidR = key; + //state->payload_algidR = alg + 0x20; //assuming DMRA approved alg values (moto patent) + } + } + + } + + } + + SBRC_END: + + //'DSP' output to file -- only RC, or RC and SB? + if (power == 1 && opts->use_dsp_output == 1 && sbrc_hex != 0) //if not NULL + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d 99 ", slot+1); //'99' is RC designation value + int k = 0; + for (i = 0; i < 24; i++) //12 bytes, SB or RC + { + //check to see if k++ starts at zero, or at 1 + int sbrc_nib = (state->dmr_embedded_signalling[slot][5][k++] << 3) | (state->dmr_embedded_signalling[slot][5][k++] << 2) | (state->dmr_embedded_signalling[slot][5][k++] << 1) | (state->dmr_embedded_signalling[slot][5][k++] << 0); + fprintf (pFile, "%X", sbrc_nib); + } + fclose (pFile); + } + +} + diff --git a/src/dmr_ms.c b/src/dmr_ms.c index de12f6d..6bb66b7 100644 --- a/src/dmr_ms.c +++ b/src/dmr_ms.c @@ -50,6 +50,11 @@ void dmrMS (dsd_opts * opts, dsd_state * state) uint8_t internalslot; uint8_t vc; + //assign as nonsensical numbers + uint8_t cc = 25; + uint8_t power = 9; //power and pre-emption indicator + uint8_t lcss = 9; + //dummy bits to pass to dburst for link control uint8_t dummy_bits[196]; memset (dummy_bits, 0, sizeof (dummy_bits)); @@ -171,7 +176,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) sync[i] = (dibit | 1) + 48; // load the superframe to do embedded signal processing - if(vc > 1 && vc < 6) //grab on vc1 values 2-5 B C D and E + if(vc > 1) //grab on vc1 values 2-5 B C D and E { state->dmr_embedded_signalling[internalslot][vc-1][i*2] = (1 & (dibit >> 1)); // bit 1 state->dmr_embedded_signalling[internalslot][vc-1][i*2+1] = (1 & dibit); // bit 0 @@ -180,10 +185,18 @@ void dmrMS (dsd_opts * opts, dsd_state * state) } sync[24] = 0; + + for(i = 0; i < 8; i++) EmbeddedSignalling[i] = syncdata[i]; + for(i = 0; i < 8; i++) EmbeddedSignalling[i + 8] = syncdata[i + 40]; + EmbeddedSignallingOk = -1; if(QR_16_7_6_decode(EmbeddedSignalling)) { EmbeddedSignallingOk = 1; + cc = ((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + power = EmbeddedSignalling[4]; + lcss = ((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); + } //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling @@ -268,6 +281,9 @@ void dmrMS (dsd_opts * opts, dsd_state * state) if (vc == 6) { dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); + //check the single burst/reverse channel opportunity + dmr_sbrc (opts, state, power); + fprintf (stderr, "\n"); dmr_alg_refresh (opts, state); } @@ -282,6 +298,12 @@ void dmrMS (dsd_opts * opts, dsd_state * state) state->last_vc_sync_time = time(NULL); vc++; + + //reset emb components + cc = 25; + power = 9; //power and pre-emption indicator + lcss = 9; + //this is necessary because we need to skip and collect dibits, not just skip them if (vc > 6) goto END; diff --git a/src/dmr_utils.c b/src/dmr_utils.c index 3ade2fc..3e56134 100644 --- a/src/dmr_utils.c +++ b/src/dmr_utils.c @@ -4,7 +4,7 @@ //Original Source - https://github.com/LouisErigHerve/dsd //Additional Functions -//Hamming17123, crc8, crc8ok functions +//Hamming17123, crc7, crc8, crc8ok functions //Original Souce - https://github.com/boatbod/op25 #include "dsd.h" @@ -121,6 +121,31 @@ bool crc8_ok(uint8_t bits[], unsigned int len) return (crc == crc8(bits,len)); } +uint8_t crc7(uint8_t bits[], unsigned int len) +{ + uint8_t crc=0; + unsigned int K = 7; + //G7(x) = x7 + x5 + x2 + x + 1 check poly below for correct (dmr rc crc7) + uint8_t poly[8] = {1,0,1,0,0,1,1,1}; // crc7 poly + uint8_t buf[256]; + if (len+K > sizeof(buf)) { + // fprintf (stderr, "crc8: buffer length %u exceeds maximum %lu\n", len+K, sizeof(buf)); + return 0; + } + memset (buf, 0, sizeof(buf)); + for (unsigned int i=0; i> 8) & 1) ^ (DMRData[i] & 1)) + { + CRC = (CRC << 1) ^ Polynome; + } + else + { + CRC <<= 1; + } + } + + /* Conserve only the 9 LSBs */ + CRC &= 0x01FF; + + /* Invert the CRC */ + CRC ^= 0x01FF; + + /* Return the CRC */ + return CRC; +} /* End ComputeCrc9Bit() */ + +/* + * @brief : This function compute the CRC-32 of the DMR data + * by using the polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + * + * @param Input : A buffer pointer of the DMR data (80 bytes) + * Rate 1/2 coded confirmed (10 data octets): 80 bit sequence (80 bytes) + * Rate 3/4 coded confirmed (16 data octets): 128 bit sequence (120 bytes) + * Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes) + * + * @param NbData : The number of bit to compute + * Rate 1/2 coded confirmed (10 data octets): 80 bit sequence (80 bytes) + * Rate 3/4 coded confirmed (16 data octets): 128 bit sequence (120 bytes) + * Rate 1 coded confirmed (22 data octets): 176 bit sequence (176 bytes) + * + * @return The 32 bit CRC + */ +uint32_t ComputeCrc32Bit(uint8_t * DMRData, uint32_t NbData) +{ + uint32_t i; + uint32_t CRC = 0x00000000; /* Initialization value = 0x00000000 */ + /* Polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + * Normal = 0x04C11DB7 + * Reversed = 0xEDB88320 + * Reciprocal = 0xDB710641 + * Reversed reciprocal = 0x82608EDB */ + uint32_t Polynome = 0x04C11DB7; + for(i = 0; i < NbData; i++) + { + if(((CRC >> 31) & 1) ^ (DMRData[i] & 1)) + { + CRC = (CRC << 1) ^ Polynome; + } + else + { + CRC <<= 1; + } + } + + /* Return the CRC */ + return CRC; +} /* End ComputeCrc32Bit() */ diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 9bf44b2..39748e2 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -141,9 +141,9 @@ processFrame (dsd_opts * opts, dsd_state * state) //print manufacturer strings to branding, disabled 0x10 moto other systems can use that fid set //0x06 is trident, but when searching, apparently, they developed con+, but was bought by moto? - if (state->dmr_mfid == 0x10) ; //sprintf (state->dmr_branding, "%s", "Motorola"); - else if (state->dmr_mfid == 0x68) sprintf (state->dmr_branding, "%s", "Hytera"); - else if (state->dmr_mfid == 0x58) sprintf (state->dmr_branding, "%s", "Tait"); + if (state->dmr_mfid == 0x10) ; //sprintf (state->dmr_branding, "%s", "Motorola"); + else if (state->dmr_mfid == 0x68) sprintf (state->dmr_branding, "%s", " Hytera"); + else if (state->dmr_mfid == 0x58) sprintf (state->dmr_branding, "%s", " Tait"); //disabling these due to random data decodes setting an odd mfid, could be legit, but only for that one packet? //or, its just a decode error somewhere diff --git a/src/dsd_main.c b/src/dsd_main.c index 7157c46..9f6a0e4 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -52,7 +52,7 @@ char * FM_banner[9] = { " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ", " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗", " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝", - " 'Lite' Edition v2.0.0-17-gdcb21f2 Windows 32-bit RC2b " + " 'Lite' Edition v2.0.0-18-g67661c2 Windows 32-bit RC2b " }; int @@ -321,8 +321,8 @@ noCarrier (dsd_opts * opts, dsd_state * state) memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps)); //REMUS! multi-purpose call_string - sprintf (state->call_string[0], "%s", " "); //20 spaces - sprintf (state->call_string[1], "%s", " "); //20 spaces + sprintf (state->call_string[0], "%s", " "); //21 spaces + sprintf (state->call_string[1], "%s", " "); //21 spaces if (time(NULL) - state->last_cc_sync_time > 30) //thirty seconds of no carrier { @@ -846,8 +846,8 @@ initState (dsd_state * state) memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps)); //REMUS! multi-purpose call_string - sprintf (state->call_string[0], "%s", " "); //20 spaces - sprintf (state->call_string[1], "%s", " "); //20 spaces + sprintf (state->call_string[0], "%s", " "); //21 spaces + sprintf (state->call_string[1], "%s", " "); //21 spaces //late entry mi fragments memset (state->late_entry_mi_fragment, 0, sizeof (state->late_entry_mi_fragment)); diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index c5a4da0..16bb400 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2053,7 +2053,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (opts->ncurses_compact == 1) { printw ("------------------------------------------------------------------------------\n"); - printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-17-gdcb21f2 RC2b"); + printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-18-g67661c2 RC2b"); } if (opts->ncurses_compact == 0) { @@ -2065,7 +2065,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (i == 2) printw (" 'q' to Quit "); if (i == 4) printw (" MBElib %s", versionstr); if (i == 5) printw (" %s ", "Win32 RC2b"); //printw (" %s \n", GIT_TAG); - if (i == 6) printw (" %s \n", "v2.0.0-17-gdcb21f2"); //printw (" %s \n", GIT_TAG); + if (i == 6) printw (" %s \n", "v2.0.0-18-g67661c2"); //printw (" %s \n", GIT_TAG); else printw ("\n"); } attroff(COLOR_PAIR(6)); //6